多线程awaitTermination和shutdown的使用问题

最近做一个抓取网页数据的任务,由于需要抓取的数据量比较大,并且抓取的间隔比较短,每次抓取任务启动后会有多次网络请求,为了提高抓取的效率采用了多线程的方式实现
ExecutorService pool = new ThreadPoolExecutor(CORE_POOL_SIZE,MAX_POOL_SIZE, KEEPALIVETIME, TimeUnit.MILLISECONDS,new LinkedBlockingDeque<Runnable>());
for (BaseInfoPO baseInfoPO : baseInfos) {
	UseThread useThread = new UseThread(baseInfoPO 
);
pool.execute(useThread);}pool.shutdown();pool.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
初始时采用了上图的实现方式,其中CORE_POOL_SIZE为10,max_pool_size为16,采用此方法启动后发现程序一直处于运行状态,无法结束,通过jdk自带的工具JVM查看程序的执行状态后发现,此时所有线程都处于await状态

        开始时认为既然所有的线程都处于等待状态,一定是资源同步出现了问题,导致所有线程都在等待某个共享资源锁的释放,于是重新检查了一下对临界资源的处理是否存在问题,发现并没有什么问题。
        这就怪了,既然并没有任何资源占用而没有释放,为什么程序仍不能正常结束呢?
Google了一下这种情况产生的各种可能原因,仍不能解决遇到的问题,无奈之下看了一眼日志,看完后就更奇怪了,日志中显示每个线程的任务都正确的执行结束了,正常情况下java虚拟机应该停止了,这样的话应该不是子线程中出现了问题,而是主线程出现了问题,JVM中显示的10个线程不是出现了问题,而是线程池中的线程,因为 CORE_POOL_SIZE为10所以会有是10个线程处于等待状态,等待分配任务。
        接下来开始检查主线程中代码(即上图):
           其实上面的代码本身并没有任何问题,我们先来看一下java官方文档对pool.awaitTermination方法的注释:
    /**
     * Blocks until all tasks have completed execution after a shutdown
     * request, or the timeout occurs, or the current thread is
     * interrupted, whichever happens first.
     *
     * @param timeout the maximum time to wait
     * @param unit the time unit of the timeout argument
     * @return <tt>true</tt> if this executor terminated and
     *         <tt>false</tt> if the timeout elapsed before termination
     * @throws InterruptedException if interrupted while waiting
     */
大概意思是这样的:该方法调用会被阻塞,直到所有任务执行完毕并且shutdown请求被调用,或者参数中定义的timeout时间到达或者当前线程被打断,这几种情况任意一个发生了就会导致该方法的执行。
这样就明白了:
    当我们调用pool.awaitTermination时,首先该方法会被阻塞,这时会执行子线程中的任务,子线程执行完毕后该方法仍然会被阻塞,因为shutdown()方法还未被调用,而代码中将shutdown的请求放在了awaitTermination之后,这样就导致了只有awaitTermination方法执行完毕后才会执行shutdown请求,这样就造成了死锁。
        解决办法自然就很简单了,调换下位置就可以了。

  • 7
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值