线程池:三大方法、7大参数、4种拒绝策略
池化技术
程序的运行,本质:占用系统的资源!
我们需要去优化资源的使用 ===> 池化技术
例如:线程池、JDBC的连接池、内存池、对象池 等等。。。。
资源的创建、销毁十分消耗资源
池化技术:事先准备好一些资源,如果有人要用,就来我这里拿,用完之后还给我,以此来提高效率。
Java的线程池是运用场景最多的并发框架,几乎所有需要异步或者并发执行任务的程序都可以使用线程池。
合理使用线程池能带来的好处:
//工具类 Executors 三大方法; public class Demo01 { public static void main(String[] args) { ExecutorService threadPool = Executors.newSingleThreadExecutor();//单个线程 ExecutorService threadPool2 = Executors.newFixedThreadPool(5); //创建一个固定的线程池的大小 ExecutorService threadPool3 = Executors.newCachedThreadPool(); //可伸缩的 //线程池用完必须要关闭线程池 try { for (int i = 1; i <=100 ; i++) { //通过线程池创建线程 threadPool.execute(()->{ System.out.println(Thread.currentThread().getName()+ " ok"); }); } } catch (Exception e) { e.printStackTrace(); } finally { threadPool.shutdown(); } } }
源码分析
public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())); }
public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); }
public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); }
阿里巴巴Java操作手册中明确说明:对于Integer.MAX_VALUE初始值较大,所以一般情况我们要使用底层的ThreadPoolExecutor来创建线程池。
public ThreadPoolExecutor(int corePoolSize, //核心线程池大小 int maximumPoolSize, //最大的线程池大小 long keepAliveTime, //超时了没有人调用就会释放 TimeUnit unit, //超时单位 BlockingQueue<Runnable> workQueue, //阻塞队列 ThreadFactory threadFactory, //线程工厂 创建线程的 一般不用动 RejectedExecutionHandler handler //拒绝策略 ) { if (corePoolSize < 0 || maximumPoolSize <= 0 || maximumPoolSize < corePoolSize || keepAliveTime < 0) throw new IllegalArgumentException(); if (workQueue == null || threadFactory == null || handler == null) throw new NullPointerException(); this.corePoolSize = corePoolSize; this.maximumPoolSize = maximumPoolSize; this.workQueue = workQueue; this.keepAliveTime = unit.toNanos(keepAliveTime); this.threadFactory = threadFactory; this.handler = handler; }
详细说明:
1. corePoolSize(线程池的基本大小):
提交一个任务到线程池时,线程池会创建一个新的线程来执行任务。注意: 即使有空闲的基本线程能执行该任务,也会创建新的线程。
如果线程池中的线程数已经大于或等于corePoolSize,则不会创建新的线程。
如果调用了线程池的prestartAllCoreThreads()方法,线程池会提前创建并启动所有基本线程。
maximumPoolSize(线程池的最大数量): 线程池允许创建的最大线程数。
阻塞队列已满,线程数小于maximumPoolSize便可以创建新的线程执行任务。
如果使用无界的阻塞队列,该参数没有什么效果。
2. workQueue(工作队列): 用于保存等待执行的任务的阻塞队列。
4.keepAliveTime(线程活动保持时间): 线程池的工作线程空闲后,保持存活的时间。如果任务多而且任务的执行时间比较短,可以调大keepAliveTime,提高线程的利用率。
5.unit(线程活动保持时间的单位): 可选单位有DAYS、HOURS、MINUTES、毫秒、微秒、纳秒。
6.handler(饱和策略,或者又称拒绝策略): 当队列和线程池都满了,即线程池饱和了,必须采取一种策略处理提交的新任务。
7. threadFactory: 构建线程的工厂类
具体流程:
一个新的任务到线程池时,线程池的处理流程如下:
线程池的核心实现类是ThreadPoolExecutor类,用来执行提交的任务。因此,任务提交到线程池时,具体的处理流程是由ThreadPoolExecutor类的execute()方法去完成的。