Executor 是JDK5新增的对于线程调度的新框架,主要用途是用来对线程进行调度和管理,
如下是Excutor框架的整体UML关系图;

本文将基于以上图片进行线程池测试用例;
1class FetchPicket implements Callable<Integer> { 2 3 @Override 4 public Integer call() throws Exception { 5 6 System.out.println("当前线程名字为:" + Thread.currentThread().getName() + " ~~~"); 7 System.out.println("开始时间:"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())); 8 Thread.sleep(10000); 9 System.out.println("结束时间:"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())); 10 return new Random().nextInt(); 11 } 12 13 }
- newCachedThreadPool
newCachedThreadPool 方法的java doc如下:

如果没有空闲线程,按照需要创建新的线程,不过当有空闲线程时,会复用已经创建好的线程.
优点:
1,可以提高编程性能,尤其对那些寿命短,异步的任务.
注意对于超过60s未使用的线程,将会从线程池中移除.
代码如下:
1 @Test 2 public void newCachedThreadPool() { 3 4 ExecutorService newCachedThreadPool = Executors.newCachedThreadPool(); 5 for (int i = 0; i < LOOP; i++) { 6 // 使用lambada表达式 7 Future<Integer> submit = newCachedThreadPool.submit(new FetchPicket()); 8 try { 9 if (submit.get() > 0) { 10 System.out.println("callable 的返回值是:" + submit.get()); 11 } 12 } catch (InterruptedException | ExecutionException e) { 13 14 e.printStackTrace(); 15 } 16 17 } 18 newCachedThreadPool.shutdown(); 19 }
console打印如下:
1当前线程名字为:pool-1-thread-1 ~~~ 2开始时间:2017-03-29 14:47:40 3结束时间:2017-03-29 14:47:50 4callable 的返回值是:1172363209 5当前线程名字为:pool-1-thread-1 ~~~ 6开始时间:2017-03-29 14:47:50 7结束时间:2017-03-29 14:48:00 8当前线程名字为:pool-1-thread-1 ~~~ 9开始时间:2017-03-29 14:48:00 10结束时间:2017-03-29 14:48:10 11callable 的返回值是:822004726 12当前线程名字为:pool-1-thread-2 ~~~ 13开始时间:2017-03-29 14:48:10 14结束时间:2017-03-29 14:48:20 15callable 的返回值是:547995146 16当前线程名字为:pool-1-thread-2 ~~~ 17开始时间:2017-03-29 14:48:20 18结束时间:2017-03-29 14:48:30
- newFixedThreadPool
Java doc如下:

创建一个固定数目可重复利用的线程池,表现出一个共享无序的队列.如果线程池里所有的线程都是active,若在提交新的线程,这个线程将会被加到一个堵塞队列中直到有可用的线程.
1 @Test 2 public void newFixedThreadPool() throws InterruptedException, ExecutionException { 3 4 ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(SIZE); 5 for (int i = 0; i < LOOP; i++) { 6 Future<Integer> submit = newFixedThreadPool.submit(new FetchPicket()); 7 try { 8 if (submit.get() > 0) { 9 System.out.println("callable 的返回值是:" + submit.get()); 10 } 11 } catch (InterruptedException | ExecutionException e) { 12 13 e.printStackTrace(); 14 } 15 } 16 newFixedThreadPool.shutdown(); 17 }
console打印如下:
1当前线程名字为:pool-1-thread-1 ~~~ 2开始时间:2017-03-29 15:12:19 3结束时间:2017-03-29 15:12:29 4当前线程名字为:pool-1-thread-2 ~~~ 5开始时间:2017-03-29 15:12:29 6结束时间:2017-03-29 15:12:39 7callable 的返回值是:360730033 8当前线程名字为:pool-1-thread-1 ~~~ 9开始时间:2017-03-29 15:12:39 10结束时间:2017-03-29 15:12:49 11callable 的返回值是:1306633973 12当前线程名字为:pool-1-thread-2 ~~~ 13开始时间:2017-03-29 15:12:49 14结束时间:2017-03-29 15:12:59 15当前线程名字为:pool-1-thread-1 ~~~ 16开始时间:2017-03-29 15:12:59 17结束时间:2017-03-29 15:13:09 18callable 的返回值是:1154663265
newFixedThreadPool 和 newCachedThreadPool 区别?
1,newFixedThreadPool 的线程是不可复用的,而newCachedThreadPool 线程是可复用的.
2,newFixedThreadPool 将会保持线程池内的线程active除非出现异常,而newCachedThreadPool 只会保持默认时间60s,因此,newFixedThreadPool 会不断的创建线程,有可能导致oom.
3,对于任务时间短异步任务,建议使用newCachedThreadPool,而执行任务时间比较长的建议使用newFixedThreadPool
英文翻译如下:

- newScheduledThreadPool
Java doc如下:

创建一个再给定的延迟时间按日期安排进行的线程池,
代码如下:
1@Test 2 public void newScheduledThreadPool() { 3 ExecutorService newScheduledThreadPool = Executors.newScheduledThreadPool(SIZE); 4 5 for (int i = 0; i < LOOP; i++) { 6 Future<Integer> submit = newScheduledThreadPool.submit(new FetchPicket()); 7 try { 8 if (submit.get() > 0) { 9 System.out.println("callable 的返回值是:" + submit.get()); 10 } 11 } catch (InterruptedException | ExecutionException e) { 12 13 e.printStackTrace(); 14 } 15 16 } 17 newScheduledThreadPool.shutdown(); 18 }
console打印如下:
1当前线程名字为:pool-1-thread-1 ~~~ 2开始时间:2017-03-29 15:36:03 3结束时间:2017-03-29 15:36:13 4callable 的返回值是:797384947 5当前线程名字为:pool-1-thread-1 ~~~ 6开始时间:2017-03-29 15:36:13 7结束时间:2017-03-29 15:36:23 8当前线程名字为:pool-1-thread-2 ~~~ 9开始时间:2017-03-29 15:36:23 10结束时间:2017-03-29 15:36:33 11当前线程名字为:pool-1-thread-1 ~~~ 12开始时间:2017-03-29 15:36:33 13结束时间:2017-03-29 15:36:43 14callable 的返回值是:1928166459 15当前线程名字为:pool-1-thread-2 ~~~ 16开始时间:2017-03-29 15:36:43 17结束时间:2017-03-29 15:36:53
分析日志可以看出,哪个线程处于空闲状态,谁抢到资源,将会执行哪个线程.
- newSingleThreadScheduledExecutor
java doc如下

创建一个按照计划执行指令的单线程,如果该线程因为某些原因关闭,新的线程将会创建并替代他的位置.
1 @Test 2 public void newSingleThreadScheduledExecutor() { 3 ExecutorService newScheduledThreadPool = Executors.newSingleThreadScheduledExecutor(); 4 for (int i = 0; i < LOOP; i++) { 5 Future<Integer> submit = newScheduledThreadPool.submit(new FetchPicket() ); 6 try { 7 if (submit.get() > 0) { 8 System.out.println("callable 的返回值是:" + submit.get()); 9 } 10 } catch (InterruptedException | ExecutionException e) { 11 12 e.printStackTrace(); 13 } 14 15 } 16 newScheduledThreadPool.shutdown(); 17 }
console日志如下:
1当前线程名字为:pool-1-thread-1 ~~~ 2开始时间:2017-03-29 15:46:40 3结束时间:2017-03-29 15:46:50 4callable 的返回值是:387305211 5当前线程名字为:pool-1-thread-1 ~~~ 6开始时间:2017-03-29 15:46:50 7结束时间:2017-03-29 15:47:00 8callable 的返回值是:1772792044 9当前线程名字为:pool-1-thread-1 ~~~ 10开始时间:2017-03-29 15:47:00 11结束时间:2017-03-29 15:47:10 12callable 的返回值是:1354567240 13当前线程名字为:pool-1-thread-1 ~~~ 14开始时间:2017-03-29 15:47:10 15结束时间:2017-03-29 15:47:20 16当前线程名字为:pool-1-thread-1 ~~~ 17开始时间:2017-03-29 15:47:20 18结束时间:2017-03-29 15:47:30 19callable 的返回值是:1825312382
分析日志可以看出,只有一个线程在打印日志.
- newSingleThreadExecutor

代码如下:
1 @Test 2 public void newSingleThreadExecutor() { 3 4 5 ExecutorService newSingleThreadExecutor = Executors.newSingleThreadExecutor(); 6 7 for (int i = 0; i < LOOP; i++) { 8 Future<Integer> submit = newSingleThreadExecutor.submit(new FetchPicket()); 9 try { 10 if (submit.get() > 0) { 11 System.out.println("callable 的返回值是:" + submit.get()); 12 } 13 } catch (InterruptedException | ExecutionException e) { 14 15 e.printStackTrace(); 16 } 17 18 } 19 newSingleThreadExecutor.shutdown(); 20 }
console打印如下:
1当前线程名字为:pool-1-thread-1 ~~~ 2开始时间:2017-03-29 15:51:33 3结束时间:2017-03-29 15:51:43 4callable 的返回值是:1323389732 5当前线程名字为:pool-1-thread-1 ~~~ 6开始时间:2017-03-29 15:51:43 7结束时间:2017-03-29 15:51:53 8callable 的返回值是:1419085557 9当前线程名字为:pool-1-thread-1 ~~~ 10开始时间:2017-03-29 15:51:53 11结束时间:2017-03-29 15:52:03 12callable 的返回值是:423848033 13当前线程名字为:pool-1-thread-1 ~~~ 14开始时间:2017-03-29 15:52:03 15结束时间:2017-03-29 15:52:13 16callable 的返回值是:1320865693 17当前线程名字为:pool-1-thread-1 ~~~ 18开始时间:2017-03-29 15:52:13 19结束时间:2017-03-29 15:52:23
分析日志,只有一个线程在执行任务.