前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java并发:FutureTask如何完成多线程并发执行、任务结果的异步获取?以及如何避其坑

Java并发:FutureTask如何完成多线程并发执行、任务结果的异步获取?以及如何避其坑

作者头像
崔认知
发布2023-09-06 14:22:34
3440
发布2023-09-06 14:22:34
举报
文章被收录于专栏:nobodynobody

FutureTask提供的主要功能


1、(超时)获取异步任务完成后的执行结果;

2、判断异步任务是否执行完成;

3、能够取消异步执行中的任务;

4、能够重复执行任务;

源码分析FutureTask的功能


FutureTask其实类似一个代理机构,当我们提交任务的任务执行时,其实是由这个代理机构为我们触发的此任务,而且也会维护任务的结果、异常信息及任务执行过程中的状态

代码使用示例:

代码语言:javascript
复制

public class ThreadPoolConfig {
  
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        FutureTask<String> futureTask = new FutureTask(() -> {
            Thread.sleep(1000 * 3);
            return "done";
        });

        new Thread(futureTask).start();

        String result = futureTask.get();
        System.out.println(result);
    }
}

当我们提交任务时:

FutureTask这个代理会保存我们的具体任务,同时初始化任务的执行状态:

代码语言:javascript
复制
this.callable = callable;
this.state = NEW;
代码语言:javascript
复制
 /** The underlying callable; nulled out after running */
 private Callable<V> callable;
代码语言:javascript
复制
 private volatile int state;

当线程真正的执行时:

代理被线程调度执行,最终代理会执行我们的任务:

代码语言:javascript
复制
result = c.call();
ran = true;

任务执行完后,会保存任务的执行结果或异常信息及更新任务的执行状态。

当任务执行成功时,保存任务的结果到变量:

代码语言:javascript
复制
 /** The result to return or exception to throw from get() */
private Object outcome; // non-volatile, protected by state reads/writes

同时任务的执行状态:

代码语言:javascript
复制
 private static final VarHandle STATE;

当任务还未执行完毕时候,我们获取任务结果时,会阻塞:

代码语言:javascript
复制
java.util.concurrent.FutureTask#get()
java.util.concurrent.FutureTask#get(long, java.util.concurrent.TimeUnit)

如果任务的执行状态还在执行中,就会阻塞当前线程。任务执行完会更新任务的执行状态,并且唤醒被阻塞的线程。

任务结束时,需要把任务的结果值或异常保留在当前FutureTask的outcome中。

FutureTask有哪些坑


1、不调用get方法获取结果,可能永远也不知道异常信息

任务中发生的异常会保存在FutureTask中,忽略获取结果,我们可能永远丢失异常信息。

2、不用带超时的get方法获取结果,可能永远会被阻塞

在线程池中,使用

代码语言:javascript
复制
java.util.concurrent.ThreadPoolExecutor.DiscardPolicy

中的默认实现,会使的FutureTask的任务状态永远不更新,非超时get方法会永远阻塞。

小结


其实FutureTask只是我们任务的代理,会记录任务执行的结果及异常信息,并提供阻塞唤醒机制来实现线程的阻塞与等待。

并且获取结果时候,不带超时的get方法可能导致异常信息丢失,或者一直被阻塞的情况。


本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-07-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 认知科技技术团队 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档