对于经常使用第三方框架进行web开发的程序员来说,Java线程池理所应当是非常智能的,线程的生命周期应该完全由Java本身控制,我们要做的就是添加任务和执行任务。但是,最近做文档批量上传同步时发现线程池中的所有任务执行完毕后,线程并没有停止,然后做了一个测试,发现确实如此:
 
问题及现象:
 
     public static void method1() {
          BlockingQueue queue = new LinkedBlockingQueue();
          ThreadPoolExecutor executor = new ThreadPoolExecutor(3, 6, 10, TimeUnit.SECONDS, queue);   
          for ( int i = 0; i < 20; i++) {
              executor.execute( new Runnable() {
                  public void run() {
                      try {
                          System. out.println( this.hashCode()/1000);
                            for ( int j = 0; j < 10; j++) {
                               System. out.println( this.hashCode() + ":" + j);
                               Thread.sleep(this.hashCode()%2);
                          } 
                      } catch (InterruptedException e) {
                          e.printStackTrace();
                      }
                      System. out.println(String. format("thread %d finished", this.hashCode()));
                  }
              });
          }
      }
debug模式下,任务执行完后,显示的效果如下:
也就是说,任务已经执行完毕了,但是线程池中的线程并没有被回收。但是我在ThreadPoolExecutor的参数里面设置了超时时间的,好像没起作用,原因如下:
工作线程回收需要满足三个条件:

1)  参数allowCoreThreadTimeOut为true

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

3)  当前线程池大小 > 核心线程池大小corePoolSize。
 
解决一:
 
      public static void method1() {
          BlockingQueue queue = new LinkedBlockingQueue();
          ThreadPoolExecutor executor = new ThreadPoolExecutor(3, 6, 1, TimeUnit.SECONDS, queue);  
          executor.allowCoreThreadTimeOut(true);
          for ( int i = 0; i < 20; i++) {
              executor.execute( new Runnable() {
                  public void run() {
                      try {
                           System. out.println( this.hashCode()/1000);
                              for ( int j = 0; j < 10; j++) {
                                System. out.println( this.hashCode() + ":" + j);
                                Thread. sleep(this.hashCode()%2);
                           } 
                      } catch (InterruptedException e) {
                          e.printStackTrace();
                      }
                      System. out.println(String. format("thread %d finished", this.hashCode()));
                  }
              });
          }
      }
需要注意的是,allowCoreThreadTimeOut 的设置需要在任务执行之前,一般在new一个线程池后设置;在allowCoreThreadTimeOut设置为true时,ThreadPoolExecutor的keepAliveTime参数必须大于0。
 
 
解决二:
 
     public static void method1() {
          BlockingQueue queue = new LinkedBlockingQueue();
          ThreadPoolExecutor executor = new ThreadPoolExecutor(3, 6, 1, TimeUnit.SECONDS, queue);
          for ( int i = 0; i < 20; i++) {
              executor.execute( new Runnable() {
                  public void run() {
                      try {
                          System. out.println( this.hashCode()/1000);
                            for ( int j = 0; j < 10; j++) {
                               System. out.println( this.hashCode() + ":" + j);
                               Thread. sleep(this.hashCode()%2);
                          } 
                      } catch (InterruptedException e) {
                          e.printStackTrace();
                      }
                      System. out.println(String. format("thread %d finished", this.hashCode()));
                  }
              });
          }         
          executor.shutdown();
      }
在任务执行完后,调用shutdown方法,将线程池中的空闲线程回收。该方法会使得keepAliveTime参数失效。
 
 

解决Java线程池任务执行完毕后线程回收问题的更多相关文章

  1. C# 多线程 线程池(ThreadPool) 2 如何控制线程池?

    线程池启动了,但是没有方法去控制线程池,如果子线程出现了问题,难道线程池就死了吗? 我们可以设置线程池的线程数量,进行加入任务,线程池会自动分配并且合理的执行,但是控制不了又有啥意思呢. 线程池里线程 ...

  2. java并发编程(四) 线程池 & 任务执行、终止源码分析

    参考文档 线程池任务执行全过程:https://blog.csdn.net/wojiaolinaaa/article/details/51345789 线程池中断:https://www.cnblog ...

  3. C# 本进程执行完毕后再执行下一线程

    最近做了一套MES集成系统,由上料到成品使自动化运行,其中生产过程是逐步的,但是每一个动作都需要独立的线程进行数据监听,那么就需要实现线程等待. 代码: using System; using Sys ...

  4. 解决批处理命令执行完毕后自动关闭cmd窗口方法

    问题描述: 日常开发工作中,为了节省多余操作导致浪费时间,我们经常会自己建一些批处理脚本文件(xx.bat),文件中包含我们需要执行的命令,有时候我们希望执行完毕后看一下执行的结果,但是窗口执行完毕后 ...

  5. 戏(细)说Executor框架线程池任务执行全过程(下)

    上一篇文章中通过引入的一个例子介绍了在Executor框架下,提交一个任务的过程,这个过程就像我们老大的老大要找个老大来执行一个任务那样简单.并通过剖析ExecutorService的一种经典实现Th ...

  6. Java线程状态、线程start方法源码、多线程、Java线程池、如何停止一个线程

    下面将依次介绍: 1. 线程状态.Java线程状态和线程池状态 2. start方法源码 3. 什么是线程池? 4. 线程池的工作原理和使用线程池的好处 5. ThreadPoolExecutor中的 ...

  7. 戏(细)说Executor框架线程池任务执行全过程(上)

    一.前言 1.5后引入的Executor框架的最大优点是把任务的提交和执行解耦.要执行任务的人只需把Task描述清楚,然后提交即可.这个Task是怎么被执行的,被谁执行的,什么时候执行的,提交的人就不 ...

  8. Android AsyncTask内部线程池异步执行任务机制简要分析

    如下分析针对的API 25的AsyncTask的源码: 使用AsyncTask如果是调用execute方法则是同步执行任务,想要异步执行任务可以直接调用executeOnExecutor方法,多数情况 ...

  9. java线程池与五种常用线程池策略使用与解析

    背景:面试中会要求对5中线程池作分析.所以要熟知线程池的运行细节,如CachedThreadPool会引发oom吗? java线程池与五种常用线程池策略使用与解析 可选择的阻塞队列BlockingQu ...

随机推荐

  1. cvtColor

    E:/OpenCV/opencv/sources/modules/imgproc/src/color.cpp CV_RGB2GRAY:RGB--->GRAY.

  2. psdash-为开发、测试人员提供简单的方法,在web界面查看服务器的运行情况(网络,带宽,磁盘,CPU), 同时可以在web界面查看日志

    psdash是linux的系统信息web指示板主要由使用数据psutil——由此得名. github地址:https://github.com/Jahaja/psdash 特性 安装 开始 配置 截图 ...

  3. 【转】Django之Model层的F对象,Q对象以及聚合函数

    转自:https://blog.csdn.net/wsy_666/article/details/86692050 一.F对象: 作用:用于处理类属性(即model的某个列数据),类属性之间的比较.使 ...

  4. 损坏的RAID5

    损坏的RAID5 string讀入卡cin 関同步 ios::sync_with_stdio(false) 由塊號映射到具體位置 塊號id對應第col個字符串 字符串開始的位置st #include& ...

  5. es之文档更新过程中并发冲突问题

    1:乐观锁控制 ES是分布式的,也是异步并发的,我们的复制请求是并行发送的:这就意味着请求到达目的地的顺序是不可控制的,是乱序的: 如果是乱序的方式,很有可能出现这样的一个问题,新version的文档 ...

  6. (二)SQL -- 查询

    主要包含以下内容: 单表查询.子查询.多表查询(左连接右连接等).合并查询 单表查询: 基础查询语句: select 列名 from 表名 where 条件 group by 列名 order by ...

  7. NOIP2002-字串变换【双向BFS】

    NOIP2002-字串变换 Description 已知有两个字串A,BA,B及一组字串变换的规则(至多66个规则): A_1A1​ ->B_1B1​ A_2A2​ -> B_2B2​ 规 ...

  8. Java中创建String的两种方式

    1.在Java中,创建一个字符串有两种方式 String x = "abc";String y = new String("abc"); 这两种方式有什么区别呢 ...

  9. java8 stream初试,map排序,list去重,统计重复元素个数,获取map的key集合和value集合

    //定义一个100元素的集合,包含A-Z List<String> list = new LinkedList<>(); for (int i =0;i<100;i++) ...

  10. 启动webpack-dev-server错误,ERROR in main.js from UglifyJs Unexpected token: name «element», expected: punc «;»

    启动webpack-dev-server出现以下错误 ERROR in main.js from UglifyJsUnexpected token: name «element», expected: ...