Java Runnable Callable FutureTask的关系概括和使用方式

本文详细介绍了Java中Runnable、Callable和FutureTask三者的关系及其使用。通过实例展示了如何通过FutureTask获取线程执行的返回值,以及如何在Runnable中设置返回值。最后指出,直接使用Callable比通过Runnable加额外包装更方便。
摘要由CSDN通过智能技术生成

线程只能执行Runnable任务,但是Runnable任务无法获得返回值。

Callable任务可以获取返回值,但是无法直接通过new Thread.start()方法运行任务。

因此有了FutrueTask这个类型的任务。既可以直接丢到Thread里面执行,又可以获取返回值。

这三者的关系,网上很多。

下面直接通过new Thread().start()来运行多线程

/**
 * Runnable
 * Callable
 * FutureTask
 */
@Slf4j
public class ThreadTest {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        new Thread(new Runnable() { // 最基础的新建线程的方式~
            @Override
            public void run() {
                log.info("Runnable运行。。。");
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();

        FutureTask<String> futureTask1 = new FutureTask<>(new Callable<String>() {
            @Override
            public String call() throws Exception {
                log.info("FutureTask.Callable运行。。。");
                Thread.sleep(3000);
                return "futureTask.callable";
            }
        }); // 通过FutureTask+Callable的方式,获取线程运行结果的返回值
        new Thread(futureTask1).start();
        String rslt1 = futureTask1.get();
        log.info("异步等待获取到了futureTask1的返回值: {}", rslt1);

        // 因为FutureTask的构造函数,对result入参有final的要求,所以不能直接用String,需要新建一个Wrapper类
        ResultWrapper rslt2 = new ResultWrapper(); // 这里赋值null,Runnable里的set方法就会NPE
        FutureTask<ResultWrapper> futureTask2 = new FutureTask<>(new Runnable() {
            @Override
            public void run() {
                log.info("FutureTask.Runnable运行。。。");
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                rslt2.setResult("futureTask.runnable");
            }
        }, rslt2); // 通过FutureTask+Runnable+Result的方式,获取线程运行结果的返回值
        new Thread(futureTask2).start();
        ResultWrapper rslt2_ = futureTask2.get();
        log.info("异步等待获取到了futureTask2的返回值: {}", rslt2.getResult());

        // 这样看来,通过Runnable+Result来获取返回值的途径,太麻烦了,还是直接用Callable吧!
    }

    @Getter
    @Setter
    private static class ResultWrapper {
        private String result;
    }
}

2022-02-13 13:26:14 [INFO] [Thread-0|cn.line.ThreadTest:17] Runnable运行。。。
2022-02-13 13:26:14 [INFO] [Thread-1|cn.line.ThreadTest:29] FutureTask.Callable运行。。。
2022-02-13 13:26:17 [INFO] [main|cn.line.ThreadTest:36] 异步等待获取到了futureTask1的返回值: futureTask.callable
2022-02-13 13:26:25 [INFO] [Thread-2|cn.line.ThreadTest:43] FutureTask.Runnable运行。。。
2022-02-13 13:26:31 [INFO] [main|cn.line.ThreadTest:55] 异步等待获取到了futureTask2的返回值: futureTask.runnable
 

代码比较随意。由于FutureTask的ge()方法,是阻塞的,因此后面几个FutureTask任务,从结果上来看,都是同步执行的。假如把获取异步结果的get()方法,都放到main函数的末尾去执行的话,就算是真正的异步、并发的了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值