解决Java线程池任务执行完毕后线程回收问题
2015-12-02 09:20
453 查看
转载请注明出处:/article/6001036.html
对于经常使用第三方框架进行web开发的程序员来说,Java线程池理所应当是非常智能的,线程的生命周期应该完全由Java本身控制,我们要做的就是添加任务和执行任务。但是,最近做文档批量上传同步时发现线程池中的所有任务执行完毕后,线程并没有停止,然后做了一个测试,发现确实如此:
问题及现象:
解决一:
解决二:
对于经常使用第三方框架进行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参数失效。 |
相关文章推荐
- spring声明式事物控制的注意事项
- java 多线程例题
- struts2接受中文乱码
- Java开发信仰者
- java中转发和重定向的区别
- java中的class 与Class , A.class 与 A.getClass() 到底有什么 不同
- Java学习之多态
- Spring AOP 实现原理与 CGLIB 应用
- java打开指定文件(运行指定程序exe)
- Java算法---求面积
- 详解Java的Struts框架中上传文件和客户端验证的实现
- 关于jndi(Java Naming and Directory Interface)java的命名与目录实例的接口
- [007]打开Eclipse 在loading workbench状态闪退
- 使用Eclipse-Maven-git做Java开发(10)--转换不符合maven结构的工程
- java读取 500M 以上文件,java读取大文件
- java SSH框架 SSM框架 SSI框架 源码
- Java代理系列-静态代理
- 继承
- java垃圾回收机制
- java编程知识--初始化