线程池使用FutureTask时候需要注意的一点事

8.4 线程池使用FutureTask时候需要注意的一点事

线程池使用FutureTask的时候如果拒绝策略设置为了 DiscardPolicyDiscardOldestPolicy并且在被拒绝的任务的Future对象上调用无参get方法那么调用线程会一直被阻塞。

问题复现

下面就通过一个简单的例子来复现问题:

0?wx_fmt=png

0?wx_fmt=png

运行代码结果为:

0?wx_fmt=png

image.png

  • 代码(1)创建了一个单线程并且队列元素个数为1的线程池,并且拒绝策略设置为了DiscardPolicy

  • 代码(2)向线程池提交了一个任务one,那么这个任务会使用唯一的一个线程进行执行,任务在打印 start runable one后会阻塞该线程5s.

  • 代码(3)向线程池提交了一个任务two,这时候会把任务two放入到阻塞队列

  • 代码(4)向线程池提交任务three,由于队列已经满了则会触发拒绝策略丢弃任务three,从执行结果看在任务one阻塞的5s内,主线程执行到了代码(5)等待任务one执行完毕,当任务one执行完毕后代码(5)返回,主线程打印出task one null。任务one执行完成后线程池的唯一线程会去队列里面取出任务two并执行所以输出start runable two然后代码(6)会返回,这时候主线程输出task two null,然后执行代码(7)等待任务three执行完毕,从执行结果看代码(7)会一直阻塞不会返回,至此问题产生,如果把拒绝策略修改为DiscardOldestPolicy也会存在有一个任务的get方法一直阻塞只是现在是任务two被阻塞。但是如果拒绝策略设置为默认的AbortPolicy则会正常返回,并且会输出如下结果:

0?wx_fmt=png

问题分析

要分析这个问题需要看下线程池的submit方法里面做了什么,submit方法代码如下:

0?wx_fmt=png

根据代码可以总结如下:

  • 代码(1)装饰Runnable为FutureTask对象,然后调用线程池的execute方法

  • 代码(2) 如果线程个数消息核心线程数则新增处理线程处理

  • 代码(3)如果当前线程个数已经达到核心线程数则任务放入队列

  • 代码(4)尝试新增处理线程进行处理,失败则进行代码(5),否者直接使用新线程处理

  • 代码(5)执行具体拒绝策略。

所以要分析上面例子中问题所在只需要看步骤(5)对被拒绝任务的影响,这里先看下拒绝策略DiscardPolicy的代码:

0?wx_fmt=png

0?wx_fmt=png

0?wx_fmt=png

0?wx_fmt=png

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值