FutureTask源码2
@SuppressWarnings({"unchecked","restriction"}) public class FutureTask1<V> implements RunnableFuture<V> { /* 任务可能出现的状态转换 NEW新建 -> COMPLETING即将完成 -> NORMAL正常结束 NEW新建 -> COMPLETING即将完成 -> EXCEPTIONAL异常 NEW新建 -> CANCELLED被取消 NEW新建 -> INTERRUPTING即将被中断 -> INTERRUPTED已经被中断 第一种:初始化状态:NEW新建 第二种:中间状态:COMPLETING即将完成,INTERRUPTING即将被中断 第三种:终端状态:NORMAL正常结束,EXCEPTIONAL异常,CANCELLED被取消,INTERRUPTED已经被中断 */ private volatile int state;//任务当前状态,任务的状态可能被其他线程修改,所以要CAS。 private static final int NEW = 0;//新建 private static final int COMPLETING = 1;//即将完成。get(),finishCompletion(),awaitDone()使用这个状态。 private static final int NORMAL = 2;//正常结束,返回结果值。report()使用这个变量。 private static final int EXCEPTIONAL = 3;//异常,不返回结果值,抛出异常。没有使用这个状态。 private static final int CANCELLED = 4;//被取消,不返回结果值,抛出异常。report(),isCanceld()方法使用这个变量。 private static final int INTERRUPTING = 5;//即将被中断,不返回结果值,抛出异常。run()方法最后会使用这个状态。 private static final int INTERRUPTED = 6;//已经被中断,不返回结果值,抛出异常。没有使用这个状态。 //FutureTask里面只能是callable,即使传进来Runnable也会转换为callable, //也就是FutureTask真正执行的任务。Thread里面只能丢Runnable,要想FutureTask丢到线程池里面去,也必须是Runnable。 //finishCompletion()置为null private Callable<V> callable; private Object outcome;//get()返回的结果 private volatile Thread runner;//执行callable任务的线程,它是CAS操作。run()的最后finally置为null。 private volatile WaitNode waiters;//等待结果的线程集合 //根据状态s决定是否返回结果 private V report(int s) throws ExecutionException { Object x = outcome;//我们在set()方法的时候把结果写进outcome的 if (s == NORMAL)//只有是正常才返回结果。其余 return (V) x; if (s >= CANCELLED)//CANCELLED4被取消,INTERRUPTING5即将被中断,INTERRUPTED6已经被中断, throw new CancellationException(); throw new ExecutionException((Throwable) x); } //把Callable封装为FutureTask1 public FutureTask1(Callable<V> callable) { if (callable == null) throw new NullPointerException(); this.callable = callable; this.state = NEW; } //把Runnable封装为FutureTask1,result是预期值。 public FutureTask1(Runnable runnable, V result) { this.callable = Executors1.callable(runnable, result);//runnbale封装为callable this.state = NEW; } //判断是否取消了,包括cancel(false);和cancel(true); public boolean isCancelled() { return state >= CANCELLED;//CANCELLED被取消,INTERRUPTING即将被中断,INTERRUPTED已经被中断 } //任务是否结束,不一定是成功任务,取消了,出异常了,被中断了,也是结束,包括cancel(false);和cancel(true);run(),setException(),set(), public boolean isDone() { return state != NEW; } //取消任务。如果是false NEW0->CANCELLED4 true: NEW ->INTERRUPTING5->中断线程->INTERRUPTED6 public boolean cancel(boolean mayInterruptIfRunning) { //fasle&&:处于不是新建状态:返回fasle,状态不变。 //true&&false:处于新建状态,但是状态设置失败:返回fasle,状态不变。 if (!(state == NEW && UNSAFE.compareAndSwapInt(this, stateOffset, NEW, mayInterruptIfRunning ? INTERRUPTING : CANCELLED)))//即将被中断5,被取消4 return false; //true&&true:是新建状态,并且 状态设置成功(将其置为INTERRUPTING5或者CANCELLED4):继续状态变为INTERRUPTED6 try { if (mayInterruptIfRunning) {//true才继续变为INTERRUPTED try { Thread t = runner; if (t != null) t.interrupt();//使用了线程中断的方法来达到取消任务的目的,设置中断标记=true } finally { // final 已经被中断6 UNSAFE.putOrderedInt(this, stateOffset, INTERRUPTED);//6 } } } finally { finishCompletion(); } return true; } //获取执行结果,阻塞,获得Callable的返回值 public V get() throws InterruptedException, ExecutionException { int s = state; if (s <= COMPLETING)//COMPLETING1即将完成,NEW新建,如果任务还没执行完成,就等待任务先执行完成 s = awaitDone(false, 0L); //s > COMPLETING:正常结束,异常,被取消,即将被中断,已经被中断 return report(s); } //获取任务执行的结果,并且有超时机制 public V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { if (unit == null) throw new NullPointerException(); int s = state; //带有超时时间的get(),如果超过指定时间,就会抛出一个TimeoutException if (s <= COMPLETING && (s = awaitDone(true, unit.toNanos(timeout))) <= COMPLETING) throw new TimeoutException(); return report(s); } protected void done() { } protected void set(V v) {//先设置即将完成,再设置正常结束 if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {//即将完成1 outcome = v;//把任务执行的结果写入到outcome当中, UNSAFE.putOrderedInt(this, stateOffset, NORMAL); //final 正常结束2 finishCompletion();//唤醒等待结果的线程 } } //修改当前任务的状态 protected void setException(Throwable t) {//先设置即将完成,再设置异常 if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {//即将完成1 outcome = t;//把任务执行的结果写入到outcome当中, UNSAFE.putOrderedInt(this, stateOffset, EXCEPTIONAL); // final 异常3 finishCompletion();//唤醒等待结果的线程 } } //任务起动就调这个方法。 public void run() { //true||:不是新建,已经执行了,就不执行 //fasle||true:是新建,runner设置当前线程失败了,就不执行 if (state != NEW || !UNSAFE.compareAndSwapObject(this, runnerOffset, null, Thread.currentThread()))//不能多线程进来 return; //false||fasle:是新建,设置runner成功就进去 try { Callable<V> c = callable; if (c != null && state == NEW) { V result; boolean ran; try { result = c.call();//Callable的call方法,如果是Runnable封装的Callable,call方法返回的是RunnableAdapter的期望值。 ran = true; } catch (Throwable ex) {//call()抛出了异常 result = null; ran = false; setException(ex);//状态不是NEW就不设置异常结果。先设置即将完成,再设置异常。设置1 3 } if (ran) set(result);//设置结果,状态不是NEW就不设置结果。先设置即将完成,再设置正常结束。设置1 2。 } } finally { //在任务执行的过程中,可能会调用cancel(),这里主要是不想让中断操作逃逸到run()方法之外 runner = null;//可以多线程进来了 int s = state; if (s >= INTERRUPTING)//即将被中断5和已经被中断6。调用了cancel(true)现在s=5|6。调用cancel(false)=4不会进来。 handlePossibleCancellationInterrupt(s); } } protected boolean runAndReset() { if (state != NEW || !UNSAFE.compareAndSwapObject(this, runnerOffset, null, Thread.currentThread())) return false; boolean ran = false; int s = state; try { Callable<V> c = callable; if (c != null && s == NEW) { try { c.call(); // don't set result ran = true; } catch (Throwable ex) { setException(ex); } } } finally { //在任务执行的过程中,可能会调用cancel(),这里主要是不想让中断操作逃逸到run()方法之外 runner = null; s = state; if (s >= INTERRUPTING)//INTERRUPTING5即将被中断,INTERRUPTED6已经被中断。调用了cancel(true)。 handlePossibleCancellationInterrupt(s); } return ran && s == NEW; } private void handlePossibleCancellationInterrupt(int s) { if (s == INTERRUPTING)//5,如果cancel(true)并且现在是5 while (state == INTERRUPTING) Thread.yield(); // 避免过多的CPU时间放在这个for循环的自旋上,让步等着变为INTERRUPTED6,等着runner线程被设置中断标记在退出,就是在收集cancel(true)的中断标记再出去。 // assert state == INTERRUPTED; // 清除cancel(true)的中断,中断是任务task和调用者通信的机制, // Thread.interrupted(); //重置中断状态为未中断=false; isInterrupted不会重置中断状态; } static final class WaitNode { volatile Thread thread; volatile WaitNode next;//下一个 WaitNode() { thread = Thread.currentThread(); } } //成功|取消 完成任务后唤醒等待结果的线程。cancel()设置s=4|6后调用这个方法,run()正常完成设置s=2,run()异常完成设置s=3后调用这个方法。 //awaitDone()唤醒的线程走if(s > COMPLETING1)返回状态值去get()获取结果。 private void finishCompletion() { assert state > COMPLETING;//正常结束,异常,被取消,即将被中断,已经被中断 for (WaitNode q; (q = waiters) != null;) {//从头开始唤醒 //设置为null之后,其他get线程看到状态>1,直接获取结果,不加入waiters队列。 //如果其他线程成功加入到了另一个新的waiters队列,此时唤醒失败,就要另一个线程他自己去退出。 //这里准备开始清空等待队列了,就要阻止其他线程进到队列来(通过状态值),如果清空后还是进到队列去了,就要线程自己处理。 if (UNSAFE.compareAndSwapObject(this, waitersOffset, q, null)) { for (;;) { Thread t = q.thread; if (t != null) { q.thread = null;//thread属性置为null LockSupport.unpark(t);//唤醒的是获取结果的awaitDone()阻塞的线程 } WaitNode next = q.next; if (next == null) break; q.next = null; //gc q,q.next不会回收,因为还有next指向在。 System.gc(); System.gc(); System.gc(); System.gc(); System.gc(); q = next; } break; } } //一个钩子方法,本类中,它是一个空实现,在子类中可以重写它。 done(); //最后把callable置为null. callable = null; // to reduce footprint } //等待任务完成,多线程进来,唤醒之后,返回状态去get获取结果。2个出口。 private int awaitDone(boolean timed, long nanos) throws InterruptedException { final long deadline = timed ? System.nanoTime() + nanos : 0L;//超时时间,如果使用了超时的get()才起作用,否则这个值不起作用 WaitNode q = null; boolean queued = false; for (;;) { if (Thread.interrupted()) {//等待结果的线程被中断了 removeWaiter(q);//移除无效节点 throw new InterruptedException();//就抛出一个中断异常 } /*分为几部操作:每一步都在一个for循环里面,只有前面一步执行了才能在下一个循环里面执行下一步*/ int s = state; //如果当前状态大于COMPLETING,说明任务已经正常完成了或者取消完成了。就去拿结果。拿到的结果可能是null就抛出异常。 //NORMAL正常结束,EXCEPTIONAL异常,CANCELLED被取消,INTERRUPTING即将被中断,INTERRUPTED已经被中断 if (s > COMPLETING) { if (q != null) q.thread = null;//回收q.thread return s;//返回任务的状态,等待结束。有可能是cancel()设置s=4|6后唤醒,有可能是run()设置s=2后唤醒,run()设置s=3后唤醒。 // 正在完成,先等一会,下次循环去初始化节点--压栈--阻塞 } else if (s == COMPLETING) Thread.yield();//避免过多的CPU时间放在这个for循环的自旋上。再次判断状态。 else if (q == null)//初始化q节点,才能去压栈,才能去阻塞。(后面2步在下一个循环中处理,会跳过这个循环) q = new WaitNode();//再次判断状态。 else if (!queued)//将q节点压入栈,它是一个cas操作。第一次是false,压栈成功变为true,再去阻塞。也就是说只有压栈了才能去阻塞。后来的在前面。 //有可能唤醒不了:finishCompletion()已经执行完了,才加入到队列就不能唤醒,就加入到一个新的waiters里面去了,就要再次循环,通过状态退出。 queued = UNSAFE.compareAndSwapObject(this, waitersOffset, q.next = waiters, q); //再次判断状态。 else if (timed) {//如果有超时限制的话,判断是否超时,如果没有超时就重试,如果超时了,就把q节点从栈中遇除 nanos = deadline - System.nanoTime(); if (nanos <= 0L) {//超时了 removeWaiter(q);//移除无效节点,多线程进来 return state;//返回状态,去获取结果。 } LockSupport.parkNanos(this, nanos);//LockSupport是一个并发工具,这里表示等待nanos秒后唤醒 } else LockSupport.park(this);//开始阻塞线程,直到任务完成了才会再次唤醒了在finishCompletion()中唤醒 } } /* 将某个节点置为无效节点,并清除栈中所有的无效节点 (通过前面的分析,应该可以推断出,无效的节点,其实就是指节点内部的thread == null) 那么产生无效节点的情况就有三种了 (1):线程被中断了 (2):s > COMPLETING,当前的任务状态> COMPLETING (3):超时 */ //如果在阻塞其间,任务被中断了,或者超时了,又或者任务已经完成了,都需要进行资源的回收。 private void removeWaiter(WaitNode node) { if (node != null) { node.thread = null;//为了GC回收node节点中的thread成员变量 retry: for (;;) {//从头到尾删除thread=null的。不仅仅删除node。 /* 多线程不会有影响,其他线程只是做了重复的事情,或者可以帮着其他线程做 */ for (WaitNode pred = null, q = waiters, s; q != null; q = s) { s = q.next; if (q.thread != null) pred = q;//q不为null,pred只要被赋值了就不为null。 else if (pred != null) { pred.next = s; if (pred.thread == null) continue retry;//如果前驱节点也是一个无效节点,则重新遍历, //q.thread异常了,pred=null,说明pred没有被赋值过,第一个q就异常了。 } else if (!UNSAFE.compareAndSwapObject(this, waitersOffset, q, s))//修改头结点是多线程在修改。修改失败就重来。 continue retry;//调到外层循环再来。 } break; } } } private static final sun.misc.Unsafe UNSAFE; private static final long stateOffset;//state private static final long runnerOffset;//runner private static final long waitersOffset;//waiters static { try { UNSAFE = java.security.AccessController .doPrivileged(new java.security.PrivilegedExceptionAction<sun.misc.Unsafe>() { public sun.misc.Unsafe run() throws Exception { Class<sun.misc.Unsafe> k = sun.misc.Unsafe.class; for (java.lang.reflect.Field f : k.getDeclaredFields()) { f.setAccessible(true); Object x = f.get(null); if (k.isInstance(x)) return k.cast(x); } throw new NoSuchFieldError("the Unsafe"); } }); Class<?> k = FutureTask1.class; stateOffset = UNSAFE.objectFieldOffset(k.getDeclaredField("state")); runnerOffset = UNSAFE.objectFieldOffset(k.getDeclaredField("runner")); waitersOffset = UNSAFE.objectFieldOffset(k.getDeclaredField("waiters")); } catch (Exception e) { throw new Error(e); } } }