Java 并发编程学习(六):FutureTask与Future

Future基本介绍

在上一篇文章中,我们用到了Future,Future具体可以用来做什么呢?要搞明白这个问题,首先要知道Future从哪儿来。下面是一个简单的例子:

import java.util.concurrent.*;


public class Main {

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ExecutorService service = Executors.newFixedThreadPool(1);

        // 创建一个runnable实例
        Runnable r = () -> {
            System.out.println("Runnable类型的任务在执行");
        };

        // 创建一个Callable实例
        Callable<String> c = () -> {
            System.out.println("Callable类型的任务在执行");
            return "finish";
        };

        // 提交任务
        Future<?> rf = service.submit(r);
        Future<String> cf = service.submit(c);

        // 1、获取任务的返回值
        String resultOfCallable = cf.get();

        // 2、判断任务是否执行结束
        if (cf.isDone()) {

        }

        // 3、取消任务的执行
        cf.cancel(true);

        // 4、判断任务是否取消了
        if (cf.isCancelled()) {

        }

        // 关闭线程池
        service.shutdown();
    }
}

从代码可以看到,向线程池提交一个任务(Runnable、Callable实例)的时候,返回一个Future对象。然后通过这个Future对象可以获知任务的状态(是否完成、获取任务返回值),或者使用Future对象可以干涉任务的执行(比如取消任务),由此可见,Future是用于管理任务的,没有任务就没有Future。

FutureTask基本介绍

FutureTask可以用来干什么?FutureTask和Future是什么关系?通过观察FutureTask类的继承关系,我们可以窥探一二。

从继承结构可以看出来,FutureTask既可以当作一个Runnable又可以当一个Future,什么意思?举个例子:

import java.util.concurrent.*;


public class Main {

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ExecutorService service = Executors.newFixedThreadPool(1);

        // 创建一个task
        Callable<String> c = () -> {
            System.out.println("[" + Thread.currentThread().getName() + "] " + "Callable task finished");
            return "finish";
        };

        // 创建一个FutureTask对象,并将其作为Runnable提交到线程池
        FutureTask<String> task = new FutureTask<>(c);
        service.submit(task);

        // 使用FutureTask获取任务执行结果
        String result = task.get();
        System.out.println("[" + Thread.currentThread().getName() + "] " +result);

        // 关闭线程池
        service.shutdown();
    }
}

运行结果:

在向线程池提交任务时,直接将FutureTask对象作为参数,因为从继承关系可以看出来FutureTask可以做为Runnable使用。在获取任务执行结果时,可以直接通过FutureTask对象的get()方法来获取,因为FutureTask类实现了Future接口。

posted @ 2021-02-03 23:05  陈玉林  阅读(150)  评论(0编辑  收藏  举报