欢迎访问昆山宝鼎软件有限公司网站! 设为首页 | 网站地图 | XML | RSS订阅 | 宝鼎邮箱 | 后台管理


新闻资讯

MENU

软件开发知识
原文出处: hcy0411

 然后是构建  <a href=昆山软件定制开拓 节点元素" class="aligncenter size-full wp-image-30532" title="Snipaste_2018-11-20_10-53-58" src="/uploads/allimg/c181121/1542J4563221Z-11131.png" />

FutureTask 是一个支持打消的异步处理惩罚器,一般在线程池顶用于异步接管callable返回值。

主要实现分三部门:

  1. 封装 Callable,昆山软件开发,然后放到线程池中去异步执行->run。
  2. 获取功效-> get。
  3. 打消任务-> cancel。

接下来主要进修下该模子如何实现。

举例说明FutureTask在线程池中的应用

// 第一步,界说线程池,
ExecutorService executor = new ThreadPoolExecutor(
        minPoolSize,
        maxPollSize,
        keepAliveTime,
        TimeUnit.SECONDS,
        new SynchronousQueue<>());

// 第二步,放到线程池中执行,返回FutureTask
FutureTask  task = executor.submit(callable);

// 第三步,获取返回值
T data = task.get();

进修FutureTask实现

类属性

//以下是FutureTask的各类状态
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;

private Callable<V> callable; //执行的任务
private Object outcome; //存储功效可能异常
private volatile Thread runner;//执行callable的线程
private volatile WaitNode waiters; //挪用get要领期待获取功效的线程栈

个中各类状态存在 最终状态 status>COMPLETING
1)NEW -> COMPLETING -> NORMAL(有正常功效)
2) NEW -> COMPLETING -> EXCEPTIONAL(功效为异常) 
3) NEW -> CANCELLED(无功效) 
4) NEW -> INTERRUPTING -> INTERRUPTED(无功效)

类要领

从上面举例说明开始阐明。

run()要领

FutureTask 担任 Runnable,ExecutorService submit 把提交的任务封装成 FutureTask 然后放到线程池 ThreadPoolExecutor 的 execute 执行。

public void run() {
    //假如不是初始状态可能cas配置运行线程是当前线程不乐成,直接返回
    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 {
              // 执行callable任务 这里对异常举办了catch
                result = c.call();
                ran = true;
            } catch (Throwable ex) {
                result = null;
                ran = false;
                setException(ex); // 封装异常到outcome
            }
            if (ran)
                set(result);
        }
    } finally {
        runner = null;
        int s = state;
        // 这里假如是间断中,配置成最终状态
        if (s >= INTERRUPTING)
            handlePossibleCancellationInterrupt(s);
    }
}

以上是 run 要领源码实现很简朴,理会如下:

  1. 假如不是始状态可能 cas 配置运行线程是当前线程不乐成,昆山软件开发,直接返回,防备多个线程反复执行。
  2. 执行 Callable 的 call(),即提交执行任务(这里做了catch,会捕捉执行任务的异常封装到 outcome 中)。
  3. 假如乐成执行 set 要领,封装功效。

set 要领

protected void set(V v) {
    //cas方法配置成completing状态,防备多个线程同时处理惩罚
    if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
        outcome = v; // 封装功效
        UNSAFE.putOrderedInt(this, stateOffset, NORMAL); // 最终配置成normal状态

        finishCompletion();
    }
}

理会如下:

  1. cas方法配置成completing状态,防备多个线程同时处理惩罚
  2. 封装功效到outcome,然后配置到最终状态normal
  3. 执行finishCompletion要领。

finishCompletion要领

// state > COMPLETING; 不管异常,间断,照旧执行完成,都需要执行该要领来叫醒挪用get要领阻塞的线程
private void finishCompletion() {
    // assert state > COMPLETING;
    for (WaitNode q; (q = waiters) != null;) {
        // cas 配置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
}

理会如下:

遍历waiters中的期待节点,并通过 LockSupport 叫醒每一个节点,通知每个线程,该任务执行完成(大概是执行完成,也大概 cancel,异常等)。

以上就是执行的进程,接下来阐明获取功效的进程->get。