FutureTask 实现了 RunnableFuture 这个接口,在run()方法中, 获取任务执行的结果,记录在outcome 字段中。它定义了一个state变量,记录了线程池异步任务执行的状态。通过判断任务状态和比较任务状态,来设置任务运行的结果和异常信息。它把state设置为volatile变量,可以保证它的可见性。 在构造方法中,初始化Callable对象, 并且把状态设置为NEW. 它的任务状态一共有七种。 那么,它的状态变化又有哪些可能性呢?主要包含四种情况 下面来看下它的几个重要的方法逻辑 1. run() 在这个方法里面, 先去判断当前任务的状态是否为空和是否为new, 如果是空或者不是处于新建的状态,则直接退出run方法。 接下来,通过Callable的call()方法,获取到异步任务的执行结果。如果正常,则设置结果。否则设置异常信息。在finally中,要把正在运行callable的线程设置为空,避免有多个线程同时执行call()方法。然后重新判断状态是否处于中断,如果是,则处理中断异常。 它的 set(result) 的逻辑是怎样的呢?我们来看下。 2. set(V v) 其中stateOffset 是定义当前的状态,利用UNSAFE的方法来进行比较并交换。这样做可以保证线程安全,并且不用加锁。 把任务状态设置为COMPLETING, 然后把 结果 赋值给 Object 对象 outcome,然后再把 任务状态设置为NORMAL, 表示该线程异步任务已经正常完成。在finishCompletion方法中,唤醒其他等待执行该任务的线程,最后把callable对象设置为null。 3. get() 在这个get() 方法中,会判断状态是否完成,如果任务还没完成, 就等待它完成。然后执行report()方法获取任务结果。那任务结果保存在哪里? 就是在我们刚才执行run()方法的时候,已经把结果保存在Object类型的outcome变量中。所以就是要获取outcome变量的值,然后返回。 如果任务状态是正常,就返回任务结果。 如果是取消状态,就抛出取消异常。如果是任务在执行过程中出现了异常呢?在刚才的run()方法中, 我们已经把任务执行的异常捕获保存在outcome变量中了,因此这里把 outcome变量的异常信息转为ExecutionException,然后抛出即可。 我们可以在获取线程池异步任务的结果中,捕获到异常信息,从而进行处理。 4. cancel 方法 如果要取消正在执行的任务,首先要把当前任务状态从NEW设置为INTERRUPTING,如果设置失败,则不能中断该任务。然后调用interrupt()方法把当前正在执行callable的线程中断, 再把任务状态改为INTERRUPTED, 最后唤醒其他线程,返回true。所以整个过程任务状态变化是: 5. 最后总结下一些注意点。 Future接口调用get()方法取得处理的结果值时是阻塞性的,如果调用Future对象的get()方法时,任务尚未执行完成,则调用get()方法时一直阻塞到此任务完成时为止。 Callable接口的call()方法可以有返回值,而Runnable接口的run()方法没有返回值。 Callable接口的call()方法可以声明抛出异常,而Runnable接口的run()方法不可以声明抛出异常。执行完Callable接口中的任务后,返回值是通过Future接口进行获得的。
public class FutureTask<V> implements RunnableFuture<V>
/** The underlying callable; nulled out after running */ private Callable<V> callable; /** The result to return or exception to throw from get() */ private Object outcome; // non-volatile, protected by state reads/writes /** The thread running the callable; CASed during run() */ private volatile Thread runner; /** Treiber stack of waiting threads */ private volatile WaitNode waiters;
/** * Creates a {@code FutureTask} that will, upon running, execute the * given {@code Callable}. * * @param callable the callable task * @throws NullPointerException if the callable is null */ public FutureTask(Callable<V> callable) { if (callable == null) throw new NullPointerException(); this.callable = callable; this.state = NEW; // ensure visibility of callable }
private volatile int state; private static final int NEW = 0; private static final int COMPLETING = 1; private static final int NORMAL = 2; private static final int EXCEPTIONAL = 3; private static final int CANCELLED = 4; private static final int INTERRUPTING = 5; private static final int INTERRUPTED = 6;
* NEW -> COMPLETING -> NORMAL * NEW -> COMPLETING -> EXCEPTIONAL * NEW -> CANCELLED * NEW -> INTERRUPTING -> INTERRUPTED
public void run() { if (state != NEW || !UNSAFE.compareAndSwapObject(this, runnerOffset, null, Thread.currentThread())) return; try { Callable<V> c = callable; if (c != null && state == NEW) { V result; boolean ran; try { result = c.call(); ran = true; } catch (Throwable ex) { result = null; ran = false; setException(ex); } if (ran) set(result); } } finally { // runner must be non-null until state is settled to // prevent concurrent calls to run() runner = null; // state must be re-read after nulling runner to prevent // leaked interrupts int s = state; if (s >= INTERRUPTING) handlePossibleCancellationInterrupt(s); } }
/** * Sets the result of this future to the given value unless * this future has already been set or has been cancelled. * * <p>This method is invoked internally by the {@link #run} method * upon successful completion of the computation. * * @param v the value */ protected void set(V v) { if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) { outcome = v; UNSAFE.putOrderedInt(this, stateOffset, NORMAL); // final state finishCompletion(); } }
// Unsafe mechanics private static final sun.misc.Unsafe UNSAFE; private static final long stateOffset; private static final long runnerOffset; private static final long waitersOffset; static { try { UNSAFE = sun.misc.Unsafe.getUnsafe(); Class<?> k = FutureTask.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); } }
/** * Removes and signals all waiting threads, invokes done(), and * nulls out callable. */ private void finishCompletion() { // assert state > COMPLETING; for (WaitNode q; (q = waiters) != null;) { if (UNSAFE.compareAndSwapObject(this, waitersOffset, q, null)) { for (;;) { Thread t = q.thread; if (t != null) { q.thread = null; LockSupport.unpark(t); } WaitNode next = q.next; if (next == null) break; q.next = null; // unlink to help gc q = next; } break; } } done(); callable = null; // to reduce footprint }
/** * @throws CancellationException {@inheritDoc} */ public V get() throws InterruptedException, ExecutionException { int s = state; if (s <= COMPLETING) s = awaitDone(false, 0L); return report(s); }
/** * Returns result or throws exception for completed task. * * @param s completed state value */ @SuppressWarnings("unchecked") private V report(int s) throws ExecutionException { Object x = outcome; if (s == NORMAL) return (V)x; if (s >= CANCELLED) throw new CancellationException(); throw new ExecutionException((Throwable)x); }
public boolean cancel(boolean mayInterruptIfRunning) { if (!(state == NEW && UNSAFE.compareAndSwapInt(this, stateOffset, NEW, mayInterruptIfRunning ? INTERRUPTING : CANCELLED))) return false; try { // in case call to interrupt throws exception if (mayInterruptIfRunning) { try { Thread t = runner; if (t != null) t.interrupt(); } finally { // final state UNSAFE.putOrderedInt(this, stateOffset, INTERRUPTED); } } } finally { finishCompletion(); } return true; }
NEW -> INTERRUPTING -> INTERRUPTED
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算