FutureTask

前言

在读别人写的代码的时候偶尔看到别人用futuretask实现多线程处理业务逻辑,因为不清楚它底层是如何做到的所以对于它的异步处理逻辑挺感兴趣的,因此当前这篇文章就是用来探索一下这个问题。

一.   测试代码

上测试代码。

二.  FutureTask类

1.1类注释

该类是实现了RunnableFuture接口的类,而RunnableFuture接口又是继承了runnable与future接口。

上它的注释说明:

它就说能做到一部计算,主要就是对实现了callable与runnable接口的对象进行包装,然后提交给executor帮执行。

1.2 关键成员注释

1.callable就是用来保存从构造函数传进来的那个实现了callable接口的匿名子类

2. outcome就是用来保存callable接口的call方法返回值的对象。

3,runner保存运行当前callable的线程的引用。

4.WaitNode保存调用行callable接口的线程的线程,就是说一般当线程调用task.get()方法的时候会挂起,然后等待任务线程执行完,并在返回结果的前一刻会将前者挂起的线程唤醒。

1.3 FutureTask构造函数

1.3.1  以callable接口为参数的构造器

可以看到如果传进来的对象是callable的子类对象就使用这个构造器,然后并将该callable引用地址赋值给this.callable.

1.3.2  以runnable接口为参数的构造器

如果是实现了runnable接口的对象的话,走下面的构造函数

砸门再康一下,Executors的callable方法。如下面代码看到的是将runnable对象包装成了一个适配器。

我们再追下去看这个适配器模式实现接口转换的代码---------其实就是在Executors类下创建一个静态内部类,然后RunnableAdapter实现了Callable接口,并在call方法下调用其持有从Runnable对象的task方法。这里的返回值就是result,随意result在与runnable进行传进来的时候目前看到是不参与计算的。/(ㄒoㄒ)/~~

1.4 FutureTask的run方法

这个run方法就是实现了runnable接口的run方法,核心方法呀,下面最主要的一行代码当然是c.call()方法,这里就执行了用户自己重写的call方法的业务逻辑。

1.4 FutureTask的set方法

这个方法就是用于唤醒已经挂起的另一个线程通知它接收计算的结果。

看outcome就是用来保存result的值。

1.5  FutureTask的finishCompletion()方法

调用该方法就是唤醒等待计算结果而被挂起的那个线程。

核心的两个局部成员:

1.WaitNode用于保存已经被挂起的线程的对象,然后当计算线程计算完结果后就便利这个链表寻找对应的线程进行唤醒。

2.另一个是LockSupport.unpark实现唤醒等待线程。

LockSupport的unpark方法还是委托了Unsafe对象实现线程唤醒。

1.6  FutureTask的get()方法

get方法的核心方法还是awaitDone方法

1.7  FutureTask的awaitDone方法

不难看到其下面是有个死循环,一直监听state状态,当反复遍历几次还没执行结束后就执行

就创建一个waiteNode节点并添加到链表中,然后调用LockSupport的park方法将当前线程挂起。

1.7  LockSupport的怕park方法

其实真正能将线程挂起的方法就是unsafe方法的park方法了。


总结

1.这里说的异步就是两个线程共同协作处理一个任务,一个线程负责计算,另一个线程负责获取当前结果然后继续向下处理,所以两个线程有序工作就需要一套通信机制,当要结果的线程没能等到计算的线程返回的结果的时候就挂起来,当负责计算的线程将结果计算出来后就将前者唤醒让它提取计算结果。

2.以runnable作为构造参数传进的futruetask其result也是作为参数被传进去保存,感觉没啥用一样。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
FutureTask是一个实现了RunnableFuture接口的类,它继承了Runnable和Future接口。因此,FutureTask既可以被当作一个Runnable来使用,也可以被当作一个Future来使用。 FutureTask实现了Future接口,完成了对Future接口的基本实现。除了实现了Future接口以外,FutureTask还实现了Runnable接口,这意味着它可以交由Executor执行,也可以直接用线程调用执行(futureTask.run())。 FutureTask具有三种执行状态:未启动、已启动和已完成。未启动指的是在调用run()方法之前,FutureTask处于未启动状态。已启动指的是FutureTask对象的run方法正在执行过程中,FutureTask处于已启动状态。已完成指的是FutureTask正常执行结束,或者被取消,或者执行过程中抛出异常而导致中断而结束。 在ThreadPoolExecutor的submit方法中,返回的是一个Future的实现,而这个实现就是FutureTask的一个具体实例。FutureTask帮助实现了具体的任务执行,并与Future接口中的get方法关联起来。 总结起来,FutureTask是一个能够同时担任Runnable和Future角色的类,它可以作为一个任务提交给线程池执行,也可以通过get方法来获取任务执行的结果。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [【第十二篇】Java 线程池FutureFutureTask【重点】](https://blog.csdn.net/weixin_42039228/article/details/123198358)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [FutureTask简介](https://blog.csdn.net/u014516601/article/details/125123415)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值