test/java/lang/ref/EarlyTimeout.java

Print this page

        

@@ -31,10 +31,11 @@
 import java.lang.System;
 import java.lang.ref.Reference;
 import java.lang.ref.ReferenceQueue;
 import java.lang.ref.WeakReference;
 import java.util.concurrent.CountDownLatch;
+import static java.util.concurrent.TimeUnit.NANOSECONDS;
 
 /**
  * In order to demonstrate the issue we make several threads (two appears to be sufficient)
  * to block in ReferenceQueue#remove(timeout) at the same time.
  * Then, we force a reference to be enqueued by setting its referent to null and calling System.gc().

@@ -46,10 +47,12 @@
 
 public class EarlyTimeout extends Thread {
 
     static final int THREADS_COUNT = 2;
     static final int TIMEOUT = 1000;
+    static final int TOLERANCE = 16; // if elapsed time is less than timeout, and differs from it
+                                     // by no greater than specified amount, we won't treat it as error
 
     static Object referent = new Object();
     static final ReferenceQueue<Object> queue = new ReferenceQueue<Object>();
     static final WeakReference<Object> weakReference = new WeakReference<Object>(referent, queue);
     static final CountDownLatch startedSignal = new CountDownLatch(THREADS_COUNT);

@@ -75,11 +78,11 @@
         if (weakReference.get() != null) {
             throw new RuntimeException("weakReference was not cleared");
         }
         int nonNullRefCount = 0;
         for (EarlyTimeout thread : threads) {
-            if (thread.reference == null && thread.actual < TIMEOUT) {
+            if (thread.reference == null && thread.actual < TIMEOUT - TOLERANCE) {
                 throw new RuntimeException("elapsed time " + thread.actual
                         + " is less than timeout " + TIMEOUT);
             }
             if (thread.reference != null && thread.reference == weakReference) {
                 nonNullRefCount++;

@@ -91,13 +94,13 @@
     }
 
     public void run() {
         try {
             startedSignal.countDown();
-            long start = System.currentTimeMillis();
+            long start = System.nanoTime();
             reference = queue.remove(TIMEOUT);
-            actual = System.currentTimeMillis() - start;
+            actual = NANOSECONDS.toMillis(System.nanoTime() - start);
         } catch (InterruptedException ex) {
             throw new RuntimeException(ex);
         }
     }
 }