--- jsr166/src/jdk7/java/util/concurrent/FutureTask.java 2014/10/03 23:48:09 1.2 +++ jsr166/src/jdk7/java/util/concurrent/FutureTask.java 2015/03/05 00:32:52 1.4 @@ -5,6 +5,7 @@ */ package java.util.concurrent; + import java.util.concurrent.locks.LockSupport; /** @@ -375,19 +376,20 @@ public class FutureTask implements Ru WaitNode q = null; boolean queued = false; for (;;) { - if (Thread.interrupted()) { - removeWaiter(q); - throw new InterruptedException(); - } - int s = state; if (s > COMPLETING) { if (q != null) q.thread = null; return s; } - else if (s == COMPLETING) // cannot time out yet + else if (s == COMPLETING) + // We may have already promised (via isDone) that we are done + // so never return empty-handed or throw InterruptedException Thread.yield(); + else if (Thread.interrupted()) { + removeWaiter(q); + throw new InterruptedException(); + } else if (q == null) { if (timed && nanos <= 0L) return s; @@ -411,7 +413,9 @@ public class FutureTask implements Ru } parkNanos = nanos - elapsed; } - LockSupport.parkNanos(this, parkNanos); + // nanoTime may be slow; recheck before parking + if (state < COMPLETING) + LockSupport.parkNanos(this, parkNanos); } else LockSupport.park(this); @@ -451,17 +455,18 @@ public class FutureTask implements Ru } // Unsafe mechanics - private static final sun.misc.Unsafe U; + private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); private static final long STATE; private static final long RUNNER; private static final long WAITERS; static { try { - U = sun.misc.Unsafe.getUnsafe(); - Class k = FutureTask.class; - STATE = U.objectFieldOffset(k.getDeclaredField("state")); - RUNNER = U.objectFieldOffset(k.getDeclaredField("runner")); - WAITERS = U.objectFieldOffset(k.getDeclaredField("waiters")); + STATE = U.objectFieldOffset + (FutureTask.class.getDeclaredField("state")); + RUNNER = U.objectFieldOffset + (FutureTask.class.getDeclaredField("runner")); + WAITERS = U.objectFieldOffset + (FutureTask.class.getDeclaredField("waiters")); } catch (Exception e) { throw new Error(e); }