线程池产生背景:高并发项目中常常须要同时启用大量线程,所以须要建立大量线程,而频繁的建立新线程和杀死旧线程将会大大拖慢CPU的性能,所以利用线程池一次性初始化若干线程,使用时从池中弹出线程,执行完线程池再予以回收java
线程池的工做流程:主要是控制运行的线程数量,处理过程当中将任务放入队列,而后在线程建立后启动这些任务,若是线程数量超过了最大数量,超出数量的线程排队等候,等其余线程执行完毕,再从队列中取出任务执行编程
线程池的主要特色:实现线程复用、控制最大并发数;可以系统地管理线程并发
线程池的优点:ide
// 源码 public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable\>()); }
// 源码 public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable\>())); }
// 源码 public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX\_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable\>()); }
实质上,这三种线程池虽然各有特色,但底层实现的都是ThreadPoolExecutor类,也即最正统的线程池,线程池本池☺高并发
// 使用案例 import java.util.concurrent.Executors; public class NewFixedThreadPoolDemo { public static void main(String[] args) { ExecutorService threadPool = Executors.newFixedThreadPool(5); // ExecutorService threadPool = Executors.newSingleThreadExecutor(); // ExecutorService threadPool = Executors.newCachedThreadExecutor(); for(int i=0; i<10; i++){ threadPool.execute(()-> System.out.println(Thread.currentThread().getName() + "\t 办理业务")); } threadPool.shutdown(); // 关闭资源!! } }
// 代码实现 import java.util.concurrent.*; public class ThreadPoolExecutorDemo { public static void main(String[] args) { ExecutorService threadPool = new ThreadPoolExecutor(2, 5, 2L, TimeUnit.SECONDS, new LinkedBlockingDeque<>(3), Executors.defaultThreadFactory(), new ThreadPoolExecutor.DiscardPolicy()); for(int i=1; i<=10; i++){ final int temp = i; threadPool.execute(()-> System.out.println(Thread.currentThread().getName() + "\t办理业务" + temp)); } threadPool.shutdown(); } }
talk is cheap, show me the diagram工具
线程池通常时间都只会开启核心线程数量的线程,而当任务队列满了以后,线程池会启用非核心线程池区(这里描述只是逻辑分区,实际上线程之间都是同等地位),建立线程并执行任务;而当任务队列中任务变少,有些线程开始闲置,闲置时间达到设置的keepAliveTime后,线程池会注销回收这些闲置线程,直到线程数量恢复核心线程数性能
共有四种拒绝策略,以2.2中的代码为准,即设置核心线程数为二、最大线程数为五、任务队列容量为三、任务数为10;见四种策略分别的运行结果以下spa