合理利用线程池能够带来三个好处。
第一:降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
第二:提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。
第三:提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。
但是要做到合理的利用线程池,必须对其原理了如指掌。
java通过Executors提供四种线程池,分别为:
1、Executors.newCachedThreadPool(),创建一个可缓存线程池,缓冲池容量大小为Integer.MAX_VALUE,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
2、Executors.newFixedThreadPool(int) 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
3、newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
4、Executors.newSingleThreadExecutor() 创建一个单线程化(容量为1)的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
ThreadPoolExecutor提供了两个方法,用于线程池的关闭,分别是shutdown()和shutdownNow(),其中:
1、shutdown():不会立即终止线程池,而是要等所有任务缓存队列中的任务都执行完后才终止,但再也不会接受新的任务
2、shutdownNow():立即终止线程池,并尝试打断正在执行的任务,并且清空任务缓存队列,返回尚未执行的任务
创建一个可缓存线程池,缓冲池容量大小为Integer.MAX_VALUE,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
public class ThreadPoolExecutorTest { public static void main(String[] args) { ExecutorService cachedThreadPool = Executors.newCachedThreadPool(); for (int i = 0; i < 5; i++) { final int index = i; //任务提交 cachedThreadPool.execute(new Runnable() { public void run() { System.out.println(Thread.currentThread().getName() + " : " +index); } }); } //如果没有结束线程池,线程池一直是启动的。这里shutdown()和shutdownNow都可以用 cachedThreadPool.shutdown(); } }pool-1-thread-1 : 0
而如果有在任务提交时,先睡眠0.5秒,线程池为无限大,当执行第二个任务时第一个任务已经完成,会复用执行第一个任务的线程,而不用每次新建线程。
public class ThreadPoolExecutorTest { public static void main(String[] args) { ExecutorService cachedThreadPool = Executors.newCachedThreadPool(); for (int i = 0; i < 5; i++) { final int index = i; try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } //任务提交 cachedThreadPool.execute(new Runnable() { public void run() { System.out.println(Thread.currentThread().getName() + " : " +index); } }); } //如果没有结束线程池,线程池一直是启动的。这里shutdown()和shutdownNow都可以用 cachedThreadPool.shutdown(); } }pool-1-thread-1 : 0
创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
public class ThreadPoolExecutorTest { public static void main(String[] args) { ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3); for (int i = 0; i < 7; i++) { final int index = i; fixedThreadPool.execute(new Runnable() { public void run() { System.out.println(Thread.currentThread().getName() + " : " + index); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } }); } //这里不能这么关闭线程池,不然输出三个语句后 // 会有三个java.lang.InterruptedException: sleep interrupted异常 //fixedThreadPool.shutdownNow(); fixedThreadPool.shutdown(); } }pool-1-thread-1 : 0
下面这种情况是在任务提交前先睡眠0.5秒
public class ThreadPoolExecutorTest { public static void main(String[] args) { ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3); for (int i = 0; i < 7; i++) { final int index = i; try { Thread.sleep( 500); } catch (InterruptedException e) { e.printStackTrace(); } fixedThreadPool.execute(new Runnable() { public void run() { System.out.println(Thread.currentThread().getName() + " : " + index); } }); } fixedThreadPool.shutdown(); } }pool-1-thread-1 : 0
创建一个定长线程池,支持定时及周期性任务执行。延迟执行示例代码如下:
public class ThreadPoolExecutorTest { public static void main(String[] args) { ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5); scheduledThreadPool.schedule(new Runnable() { //schedule public void run() { System.out.println("delay 1 seconds"); } }, 1, TimeUnit.SECONDS); //表示延迟1秒后执行。 //没有结果输出 //scheduledThreadPool.shutdownNow(); scheduledThreadPool.shutdown(); } }定期执行示例代码如下:
public class ThreadPoolExecutorTest { public static void main(String[] args) { ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5); scheduledThreadPool.scheduleAtFixedRate(new Runnable() { //scheduleAtFixedRate public void run() { System.out.println(Thread.currentThread().getName() + " : " +"delay 1 seconds, and excute every 3 seconds"); } }, 1, 3, TimeUnit.SECONDS); //延迟1秒后每3秒执行一次,一直执行 //不管用哪个,都没有结果 //scheduledThreadPool.shutdownNow(); //scheduledThreadPool.shutdown(); } }pool-1-thread-1 : delay 1 seconds, and excute every 3 seconds
......
创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。示例代码如下
public class ThreadPoolExecutorTest { public static void main(String[] args) { ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor(); for (int i = 0; i < 5; i++) { final int index = i; singleThreadExecutor.execute(new Runnable() { public void run() { System.out.println(Thread.currentThread().getName() + " : " +index); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } }); } } }pool-1-thread-1 : 0