java 线程池超时_java线程池中的线程超时控制

2023-05-16

先MARK下一篇将JDK自带线程池的工具文,讲得挺清楚。

一些系统中的外部IO调用,比如调用第三方系统的WEBSERVICE等,尽管可以设定超时时间,但若每次调用都接近超时的上限的话,在并发较大的情况下很容易会造成系统不堪重负。此时若此调用无需实时获得调用结果,则可采用newFixedThreadPool将并发调用数限制在一定数量下,其他任务自动进入内存队列。

而开放给第三方系统的接口,在被调用时若处理较耗时,则可采用先放入线程池并立即返回的异步处理方式提高系统吞吐量。

同时,JAVA线程池也可以同时配合可持久化的任务队列来来防止任务的丢失。

最近,项目又提出,在某些场景下,还要加入线程超时机制。

于是百度之,发现被转载最多的整体思路就是: 每启动一个线程的时候,通过join(long timeout)方法或者其他类似方法(比如java.util.concurrent.Future.get(long timeout, TimeUnit unit) )启动一个监听线程,当监听线程通过上述方法判断任务线程超时,再调用interrupt或者cancel方法退出线程。

上述解决方案仔细看了下,有如下2个问题:

1.这种方式,每执行一个任务要启动2个线程,代价未免也太大了

个人解决方式:

对于每种类型的线程池,完全可以采用上文中的JDK自带线程池的实现,在提交任务的时候通过如下方法获得一个Future参数。

而对于每一个task,实现一个可获取任务启动时间的接口。

将该Future对象和提交的task对象放置于一个集合对象中,并启动一个独立线程,每隔一段时间(比如1秒)遍历该集合读写,并调用 boolean java.util.concurrent.Future.isDone()方法判断是否执行完成,若未完成,则比较task的启动时间和当前时间,若超时了,则启动关闭线程的操作。

2.如何关闭一个线程

这是前文百度到的解决方案中最误导人的地方。

首先JAVA目前的中断模型是协作式的,调用interrupt()或者cancel()方法,只会在执行线程中设置一个中断标志位。是否真正要中断,则要看具体程序的逻辑。

默认可中断的JAVA操作,主要集中于那些会让线程阻塞的操作。比如sleep(),wait()等。有个简单的判别办法,就是方法声明中是否有抛出中断异常,比如Thread.sleep(long millis) throws InterruptedException。

而诸如IO操作或者同步时锁获取等阻塞,则不可被中断(当然,java nio或者JDK1.5的显式的Lock方式有提供了支持中断的方法)。

前文百度到的范例代码,都是通过sleep()作为DEMO,这就是为什么很多人抱怨实际不起作用的原   因。

那解决方式呢? 几乎没有。强制不由分说的关闭一个线程可能会导致各种问题,比如锁不释放等。一个比较偏门的方式就是让任务代码自己实现一个关闭资源的方法,超时时由监听线程调用。比如强制close掉socket,则正在调用中的IO操作则会立刻抛出异常。这种解决方式依赖于任务线程本身的实现,的确也不是什么高明的方式。

在此求助下,如果各位有更好的关闭线程的方式,请不吝赐教!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

java 线程池超时_java线程池中的线程超时控制 的相关文章

随机推荐