您的位置:首页 > 编程语言 > Java开发

解决Java线程池任务执行完毕后线程回收问题

2015-12-02 09:20 453 查看
转载请注明出处:/article/6001036.html

对于经常使用第三方框架进行web开发的程序员来说,Java线程池理所应当是非常智能的,线程的生命周期应该完全由Java本身控制,我们要做的就是添加任务和执行任务。但是,最近做文档批量上传同步时发现线程池中的所有任务执行完毕后,线程并没有停止,然后做了一个测试,发现确实如此:

问题及现象:

[align=left] public static void method1() {[/align]
[align=left] BlockingQueue queue = new LinkedBlockingQueue();[/align]
[align=left] ThreadPoolExecutor executor = new ThreadPoolExecutor(3, 6, 10, TimeUnit.SECONDS, queue); [/align]
[align=left] for ( int i = 0; i < 20; i++) {[/align]
[align=left] executor.execute( new Runnable() {[/align]
[align=left] public void run() {[/align]
[align=left] try {[/align]
[align=left] System. out.println( this.hashCode()/1000);[/align]
[align=left] for ( int j = 0; j < 10; j++) {[/align]
[align=left] System. out.println( this.hashCode() + ":" + j);[/align]
[align=left] Thread.sleep(this.hashCode()%2);[/align]
[align=left] } [/align]
[align=left] } catch (InterruptedException e) {[/align]
[align=left] e.printStackTrace();[/align]
[align=left] }[/align]
[align=left] System. out.println(String. format("thread %d finished", this.hashCode()));[/align]
[align=left] }[/align]
[align=left] });[/align]
[align=left] }[/align]
[align=left] }[/align]
debug模式下,任务执行完后,显示的效果如下:



也就是说,任务已经执行完毕了,但是线程池中的线程并没有被回收。但是我在ThreadPoolExecutor的参数里面设置了超时时间的,好像没起作用,原因如下:

工作线程回收需要满足三个条件:
1) 参数allowCoreThreadTimeOut为true

2) 该线程在keepAliveTime时间内获取不到任务,即空闲这么长时间

3) 当前线程池大小 > 核心线程池大小corePoolSize。

解决一:

[align=left] public static void method1() {[/align]
[align=left] BlockingQueue queue = new LinkedBlockingQueue();[/align]
[align=left] ThreadPoolExecutor executor = new ThreadPoolExecutor(3, 6, 1, TimeUnit.SECONDS, queue); [/align]
[align=left] executor.allowCoreThreadTimeOut(true);[/align]
[align=left] for ( int i = 0; i < 20; i++) {[/align]
[align=left] executor.execute( new Runnable() {[/align]
[align=left] public void run() {[/align]
[align=left] try {[/align]
[align=left] System. out.println( this.hashCode()/1000);[/align]
[align=left] for ( int j = 0; j < 10; j++) {[/align]
[align=left] System. out.println( this.hashCode() + ":" + j);[/align]
[align=left] Thread. sleep(this.hashCode()%2);[/align]
[align=left] } [/align]
[align=left] } catch (InterruptedException e) {[/align]
[align=left] e.printStackTrace();[/align]
[align=left] }[/align]
[align=left] System. out.println(String. format("thread %d finished", this.hashCode()));[/align]
[align=left] }[/align]
[align=left] });[/align]
[align=left] }[/align]
[align=left] }[/align]
需要注意的是,allowCoreThreadTimeOut 的设置需要在任务执行之前,一般在new一个线程池后设置;在allowCoreThreadTimeOut设置为true时,ThreadPoolExecutor的keepAliveTime参数必须大于0。
解决二:

[align=left]public static void method1() {[/align]
[align=left] BlockingQueue queue = new LinkedBlockingQueue();[/align]
[align=left] ThreadPoolExecutor executor = new ThreadPoolExecutor(3, 6, 1, TimeUnit.SECONDS, queue);[/align]

[align=left] for ( int i = 0; i < 20; i++) {[/align]
[align=left] executor.execute( new Runnable() {[/align]
[align=left] public void run() {[/align]
[align=left] try {[/align]
[align=left] System. out.println( this.hashCode()/1000);[/align]
[align=left] for ( int j = 0; j < 10; j++) {[/align]

[align=left] System. out.println( this.hashCode() + ":" + j);[/align]
[align=left] Thread. sleep(this.hashCode()%2);[/align]
[align=left] } [/align]

[align=left] } catch (InterruptedException e) {[/align]
[align=left] e.printStackTrace();[/align]
[align=left] }[/align]
[align=left] System. out.println(String. format("thread %d finished", this.hashCode()));[/align]
[align=left] }[/align]
[align=left] });[/align]

[align=left] } [/align]

[align=left] executor.shutdown();[/align]

[align=left] }[/align]
在任务执行完后,调用shutdown方法,将线程池中的空闲线程回收。该方法会使得keepAliveTime参数失效。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: