类图中表达总体与局部的关系_谈谈Future、Callable、FutureTask关系

创建线程的两种方式

一种是实现Runnable接口,实现其run方式;另外一种是继承Thread类,重写其run方法。

这一点可以从Thread类中的注释看到:

137aaff2ca8873cb98fcc21d9f0bb153.png

Runnable

Thread类也实现了Runnable接口,Runnable接口的源码如下:

    public static  CompletableFuture supplyAsync(Supplier supplier)    public static  CompletableFuture supplyAsync(Supplier supplier,Executor executor); public static CompletableFuture runAsync(Runnable runnable); public static CompletableFuture runAsync(Runnable runnable,Executor executor);

因此,可以看得出,不管我们是实现Runnable接口,还是继承Thread类,run方式的返回类型都是void,我们都无法拿到线程运行的返回结果。

如果非要拿到线程运行的结果怎么办?Callable便应运而生了。


Callable

@FunctionalInterfacepublic interface Callable {    /**     * Computes a result, or throws an exception if unable to do so.     *     * @return computed result     * @throws Exception if unable to compute a result     */    V call() throws Exception;}

Callable还是一个函数式接口,其泛型参数类型与返回值类型一致。

为了更清晰的说明他们之间的关系,这里先放上类图结构


类图关系

7906d31aa71a4fe75e0afcaa7b98e528.png

Future

Callable接口,只是用于单纯地去获得返回值,但是什么时候去获取,或者查看线程运行的状态,就需要借助Future

Future的源码如下:

    public CompletableFuture whenComplete(BiConsumer super T, ? super Throwable> action);    public CompletableFuture whenCompleteAsync(BiConsumer super T, ? super Throwable> action);    public CompletableFuture whenCompleteAsync(BiConsumer super T, ? super Throwable> action, Executor executor);    public CompletableFuture exceptionally(Function fn);

可以看得出来,Future提供了取消任务、获取任务执行的状态与获取结果的能力。


RunnableFuture

public interface RunnableFuture extends Runnable, Future {    /**     * Sets this Future to the result of its computation     * unless it has been cancelled.     */    void run();}

RunnableFuture继承了Runnable与Future接口,没什么好说的。

以上说的,Runnable、Callable、Future以及RunnableFuture都是接口,真正干活还得靠FutureTask


FutureTask

FutureTask实现了RunnableFuture接口,而RunnableFuture继承了Runnable与Future接口,因此FutureTask既可以作为一个Runnable被Thread执行,也可以获取到Future异步计算的结果。

从上面的类图可以看到,传入一个Callable类型的参数可以构造FutureTask对象。

下面这个例子,使用构造出来的FutureTask对象,传入Thread的构造函数中,调用start方法以启动线程。

package com.qcy.testFutureTask;import java.util.concurrent.Callable;import java.util.concurrent.ExecutionException;import java.util.concurrent.FutureTask;/** * @author qcy * @create 2020/09/07 09:27:06 */public class Main {    static class Task implements Callable {        @Override        public Integer call() throws Exception {            //模拟任务耗时            Thread.sleep(2000);            return 1;        }    }    public static void main(String[] args) throws ExecutionException, InterruptedException {        //FutureTask接收一个Callable实现类        FutureTask futureTask = new FutureTask<>(new Task());        //FutureTask实现了RunnableFuture,间接实现了Runnable接口,因此可作为参数传给Thread的构造方法中        new Thread(futureTask).start();        //get()方法会阻塞2秒,输出1        int result = futureTask.get();        System.out.println(result);    }}

当然也可以将构造出来FutureTask对象,提交进线程池中。对线程池不了解的同学,可以移步这一篇文章说说线程池

package com.qcy.testFutureTask;import java.util.concurrent.*;/** * @author qcy * @create 2020/09/07 09:27:06 */public class Main {    static class Task implements Callable {        @Override        public Integer call() throws Exception {            //模拟任务耗时            Thread.sleep(2000);            return 1;        }    }    public static void main(String[] args) throws ExecutionException, InterruptedException {        ExecutorService pool = Executors.newFixedThreadPool(1);        //FutureTask接收一个Callable实现类        FutureTask futureTask = new FutureTask<>(new Task());        //这里使用一个Runnable的实现类,因此可以使用FutureTask        pool.submit(futureTask);        //get()方法会阻塞2秒,输出1        int result = futureTask.get();        System.out.println(result);        pool.shutdown();    }}

当然,ExecutorService内的submit方法,可以直接传入Callable的实现类。

package com.qcy.testFutureTask;import java.util.concurrent.*;/** * @author qcy * @create 2020/09/07 09:27:06 */public class Main {    static class Task implements Callable {        @Override        public Integer call() throws Exception {            //模拟任务耗时            Thread.sleep(2000);            return 1;        }    }    public static void main(String[] args) throws ExecutionException, InterruptedException {        ExecutorService pool = Executors.newFixedThreadPool(1);        //这里使用一个Callable的实现类,因此可以使用FutureTask        Future future = pool.submit(new Task());        //get()方法会阻塞2秒,输出1        int result = future.get();        System.out.println(result);        pool.shutdown();    }}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值