Java并发编程的艺术笔记(九)——FutureTask详解

FutureTask是一种可以取消的异步的计算任务。它的计算是通过Callable实现的,多用于耗时的计算。

一.FutureTask的三种状态

 

 二.get()和cancel()执行示意

三.使用

一般FutureTask多用于耗时的计算,主线程可以在完成自己的任务后,再去获取结果。

扫描二维码关注公众号,回复: 4869881 查看本文章

3.1 FutureTask + Thread

package concurrent;  

import java.util.Random;    
import java.util.concurrent.Callable;    
import java.util.concurrent.ExecutionException;    
import java.util.concurrent.FutureTask;    
    
/**  
 *  
 * @author Administrator  
 *  
 */    
@SuppressWarnings("all")    
public class FutureTaskDemo {    
    public static void main(String[] args) {    
        //step2:创建计算任务,作为参数,传入FutureTask   
        CalculateTask cTask = new CalculateTask();    
        FutureTask futureTask = new FutureTask(cTask);    
        //step3:将FutureTask提交给Thread执行    
        Thread pAccountThread = new Thread(futureTask);  
        System.out.println("futureTask线程现在开始启动,启动时间为:" + System.nanoTime());    
        pAccountThread.start();    
        System.out.println("主线程开始执行其他任务");    
        // 从其他账户获取总金额    
        int totalMoney = new Random().nextInt(100000);    
        System.out.println("现在你在其他账户中的总金额为" + totalMoney);    
        System.out.println("等待私有账户总金额统计完毕...");    
        // step4:测试后台的计算线程是否完成,如果未完成则等待    
        while (!futureTask.isDone()) {    
            try {    
                Thread.sleep(500);    
                System.out.println("私有账户计算未完成继续等待...");    
            } catch (InterruptedException e) {    
                e.printStackTrace();    
            }    
        }    
        System.out.println("futureTask线程计算完毕,此时时间为" + System.nanoTime());    
        Integer privateAccountMoney = null;   
        //step5:获取执行结果
        try {    
            privateAccountMoney = (Integer) futureTask.get();    
        } catch (InterruptedException e) {    
            e.printStackTrace();    
        } catch (ExecutionException e) {    
            e.printStackTrace();    
        }    
        System.out.println("您现在的总金额为:" + totalMoney + privateAccountMoney.intValue());    
    }    
}    
    
/**
 * @author admin
 *step1:封装一个计算任务,计算私有账户余额,实现Callable接口
 */
@SuppressWarnings("all")    
class CalculateTask implements Callable {    
    Integer totalMoney;    
    
    @Override    
    public Object call() throws Exception {
        //模拟耗时操作
        Thread.sleep(5000);    
        totalMoney = new Integer(new Random().nextInt(10000));    
        System.out.println("您当前有" + totalMoney + "在您的私有账户中");    
        return totalMoney;    
    }    
}

执行结果:

futureTask线程现在开始启动,启动时间为:57541141963086
主线程开始执行其他任务
现在你在其他账户中的总金额为30431
等待私有账户总金额统计完毕...
私有账户计算未完成继续等待...
私有账户计算未完成继续等待...
私有账户计算未完成继续等待...
私有账户计算未完成继续等待...
私有账户计算未完成继续等待...
私有账户计算未完成继续等待...
私有账户计算未完成继续等待...
私有账户计算未完成继续等待...
私有账户计算未完成继续等待...
您当前有4831在您的私有账户中
私有账户计算未完成继续等待...
futureTask线程计算完毕,此时时间为57546161371100
您现在的总金额为:304314831

 3.2 Future + ExecutorService

//step1 ......
//step2:创建计算任务
Task task = new Task();
//step3:创建线程池,将Callable类型的task提交给线程池执行,通过Future获取子任务的执行结果
ExecutorService executorService = Executors.newCachedThreadPool();
final Future<Boolean> future = executorService.submit(task);
//step4:通过future获取执行结果
boolean result = (boolean) future.get();

四.源码解析

4.1 状态

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;

4.2 构造函数

/**
     * 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
    }

可以看到FutrueTask传入的是一个Callable类型的变量,将传入的参数赋值给this.callable,然后设置state状态为NEW,表示这是新任务。

也可以使用Runnable+result组合成一个Callable

public static <T> Callable<T> callable(Runnable task, T result) {
    if (task == null)
        throw new NullPointerException();
    return new RunnableAdapter<T>(task, result);
}

猜你喜欢

转载自www.cnblogs.com/lingluo2017/p/10254371.html