在前面的章节我们都是直接对Thread进行管理,我们这里解释一下另一个管理Thread的类Executors。
1.例子:
package com.ray.ch17; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class Test { public static void main(String[] args) throws InterruptedException { long startTime = System.currentTimeMillis(); ExecutorService executorService = Executors.newCachedThreadPool(); CountDownLatch countDownLatch = new CountDownLatch(5); for (int i = 5; i < 10; i++) { DoneMission doneMission = new DoneMission(i, countDownLatch); executorService.execute(doneMission); } executorService.shutdown(); countDownLatch.await(); long endTime = System.currentTimeMillis(); System.out.println(); System.out.println(endTime - startTime); } } class DoneMission implements Runnable { private final int id = index++; private int count = 0; private static int index = 0; private CountDownLatch countDownLatch; public DoneMission(int count, CountDownLatch countDownLatch) { this.count = count; this.countDownLatch = countDownLatch; } public String leftMission() { return "#" + id + "(" + count + ") "; } @Override public void run() { while (count-- > 0) { System.out.print(leftMission()); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } Thread.yield(); } countDownLatch.countDown(); } }
解释:
(1)运行任务的类跟前面的基本一致
(2)使用Executors.newCachedThreadPool()生成线程池,当需要线程驱动的时候,我们可以到里面拿,它生成的线程数是有系统控制的。
2.对线程的数量做出控制
package com.ray.ch17; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class Test { public static void main(String[] args) throws InterruptedException { long startTime = System.currentTimeMillis(); ExecutorService executorService = Executors.newFixedThreadPool(5);//控制线程的数量 CountDownLatch countDownLatch = new CountDownLatch(5); for (int i = 5; i < 10; i++) { DoneMission doneMission = new DoneMission(i, countDownLatch); executorService.execute(doneMission); } executorService.shutdown(); countDownLatch.await(); long endTime = System.currentTimeMillis(); System.out.println(); System.out.println(endTime - startTime); } } class DoneMission implements Runnable { private final int id = index++; private int count = 0; private static int index = 0; private CountDownLatch countDownLatch; public DoneMission(int count, CountDownLatch countDownLatch) { this.count = count; this.countDownLatch = countDownLatch; } public String leftMission() { return "#" + id + "(" + count + ") "; } @Override public void run() { while (count-- > 0) { System.out.print(leftMission()); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } Thread.yield(); } countDownLatch.countDown(); } }
上面的代码只是替换了一句,就可以控制线程的数量,但是我们一般还是建议使用cache的那个,因为它对线程池做出来优化。特别是对于短的异步任务它具有明显优势。
3.测试不同线程运行的时间:
package com.ray.ch17; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class Test { public static void main(String[] args) throws InterruptedException { long startTime = System.currentTimeMillis(); ExecutorService executorService = Executors.newCachedThreadPool(); CountDownLatch countDownLatch = new CountDownLatch(5); for (int i = 5; i < 10; i++) { DoneMission doneMission = new DoneMission(i, countDownLatch); executorService.execute(doneMission); } executorService.shutdown(); countDownLatch.await(); long endTime = System.currentTimeMillis(); System.out.println(); System.out.println("time:"+(endTime - startTime)); } } class DoneMission implements Runnable { private final int id = index++; private int count = 0; private static int index = 0; private CountDownLatch countDownLatch; public DoneMission(int count, CountDownLatch countDownLatch) { this.count = count; this.countDownLatch = countDownLatch; } public String leftMission() { return "#" + id + "(" + count + ") "; } @Override public void run() { while (count-- > 0) { System.out.print(leftMission()); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } Thread.yield(); } countDownLatch.countDown(); } }
输出:
#0(4) #1(5) #2(6) #3(7) #4(8) #0(3) #1(4) #4(7) #3(6) #2(5) #0(2) #1(3) #3(5) #2(4) #4(6) #0(1) #1(2) #4(5) #3(4) #2(3) #0(0) #1(1) #2(2) #4(4) #3(3) #1(0) #2(1) #3(2) #4(3) #4(2) #3(1) #2(0) #3(0) #4(1) #4(0)
904
控制为3个线程:
package com.ray.ch17; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class Test { public static void main(String[] args) throws InterruptedException { long startTime = System.currentTimeMillis(); ExecutorService executorService = Executors.newFixedThreadPool(3); CountDownLatch countDownLatch = new CountDownLatch(5); for (int i = 5; i < 10; i++) { DoneMission doneMission = new DoneMission(i, countDownLatch); executorService.execute(doneMission); } executorService.shutdown(); countDownLatch.await(); long endTime = System.currentTimeMillis(); System.out.println(); System.out.println(endTime - startTime); } } class DoneMission implements Runnable { private final int id = index++; private int count = 0; private static int index = 0; private CountDownLatch countDownLatch; public DoneMission(int count, CountDownLatch countDownLatch) { this.count = count; this.countDownLatch = countDownLatch; } public String leftMission() { return "#" + id + "(" + count + ") "; } @Override public void run() { while (count-- > 0) { System.out.print(leftMission()); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } Thread.yield(); } countDownLatch.countDown(); } }
输出:
#0(4) #2(6) #1(5) #1(4) #0(3) #2(5) #0(2) #2(4) #1(3) #1(2) #2(3) #0(1) #0(0) #1(1) #2(2) #1(0) #2(1) #3(7) #3(6) #4(8) #2(0) #3(5) #4(7) #3(4) #4(6) #3(3) #4(5) #4(4) #3(2) #4(3) #3(1) #4(2) #3(0) #4(1) #4(0)
1504
控制为单线程:
package com.ray.ch17; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class Test { public static void main(String[] args) throws InterruptedException { long startTime = System.currentTimeMillis(); ExecutorService executorService = Executors.newSingleThreadExecutor(); CountDownLatch countDownLatch = new CountDownLatch(5); for (int i = 5; i < 10; i++) { DoneMission doneMission = new DoneMission(i, countDownLatch); executorService.execute(doneMission); } executorService.shutdown(); countDownLatch.await(); long endTime = System.currentTimeMillis(); System.out.println(); System.out.println(endTime - startTime); } } class DoneMission implements Runnable { private final int id = index++; private int count = 0; private static int index = 0; private CountDownLatch countDownLatch; public DoneMission(int count, CountDownLatch countDownLatch) { this.count = count; this.countDownLatch = countDownLatch; } public String leftMission() { return "#" + id + "(" + count + ") "; } @Override public void run() { while (count-- > 0) { System.out.print(leftMission()); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } Thread.yield(); } countDownLatch.countDown(); } }
输出:
#0(4) #0(3) #0(2) #0(1) #0(0) #1(5) #1(4) #1(3) #1(2) #1(1) #1(0) #2(6) #2(5) #2(4) #2(3) #2(2) #2(1) #2(0) #3(7) #3(6) #3(5) #3(4) #3(3) #3(2) #3(1) #3(0) #4(8) #4(7) #4(6) #4(5) #4(4) #4(3) #4(2) #4(1) #4(0)
3503
单线程说白了就像直接在main方法里面使用for来运行的一样。
4.关于shutdown()(下面的这段话摘自http://my.oschina.net/bairrfhoinn/blog/177639,笔者觉得他解释的已经比较清楚,其实关键是笔者比较懒,不喜欢打字)
为了关闭在 ExecutorService 中的线程,你需要调用 shutdown() 方法。ExecutorService 并不会马上关闭,而是不再接收新的任务,一旦所有的线程结束执行当前任务,ExecutorServie 才会真的关闭。所有在调用 shutdown() 方法之前提交到 ExecutorService 的任务都会执行。
如果你希望立即关闭 ExecutorService,你可以调用 shutdownNow() 方法。这个方法会尝试马上关闭所有正在执行的任务,并且跳过所有已经提交但是还没有运行的任务。但是对于正在执行的任务,是否能够成功关闭它是无法保证的,有可能他们真的被关闭掉了,也有可能它会一直执行到任务结束。
总结:这一章节主要介绍Executors的使用。
这一章节就到这里,谢谢。
-----------------------------------