1:当一个任务提交时,如果CorePool中的核心线程少于CorePoolSize,则创建一个新线程执行任务(需要全局锁)
2:如果CorePool中没有空闲的线程,那么加入BlockingQueue等待核心线程拉取任务执行
3:如果BlockingQueue已满,创建新线程后如果大于maximumPoolSize就跳转到4拒绝执行任务,如果小于就创建新线程执行任务(需要全局锁)
4:四种不同的拒绝策略,通过rejectedExecution()方法执行。
需要获取全局锁导致线程池的性能大大下降,应该尽量避免产生步骤1和步骤3
使用Executors创建线程池 :但一般都不建议这么创建线程池
package pool; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * alibab开发手册以及工作中都是用 ThreadPoolExecutor 创建线程池, * 而不是用三大方法 newSingleThreadExecutor,newFixedThreadPool,newCachedThreadPool这三种 */ public class Demo01 { public static void main(String[] args) { // 单个线程 ExecutorService threadpool = Executors.newSingleThreadExecutor(); // 固定线程池大小 //ExecutorService threadpool = Executors.newFixedThreadPool(5); // 可伸缩的,遇强则强,遇弱则弱 ExecutorService threadpool = Executors.newCachedThreadPool(); for (int i = 0; i < 10; i++) { threadpool.execute(()->{ System.out.println(Thread.currentThread().getName()+" ok"); }); } 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 LinkedBlockingQueue() { this(2147483647); }
从源码中可以看出,newSingleThreadExecutor只允许创建单个线程,其他的线程都会被放在 LinkedBlockingQueue 阻塞队列中,而 newFixedThreadPool 能够创建自定义数量的线程数,同时,两种线程池都使用 LinkedBlockingQueue 阻塞队列,而阻塞队列的长度为 Integer.MAX_VALUE = 2147483647 ,过多的创建线程可能会造成内存溢出,也就是 OOM。
public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>() ); }而在 newCachedThreadPool 线程池中将最大的线程池数量设置为 Integer.MAX_VALUE ,过多的创建线程的话也会造成一个 内存溢出,OOM。所以阿里云开发手册明确指出不建议使用这三种方式创建线程池,而是采取了自定义七大参数的方式创建线程池。
corePoolSize核心线程池,默认开启的线程池数量 maximumPoolSize 最大线程池, keepAliveTime + TimeUnit.SECONDS 除核心线程池以外的其他线程池空闲时,保持 3 秒(时间自己定义)无别的线程进来,3秒后关闭除核心线程池外的线程 ArrayBlockingQueue 阻塞队列候客区 ThreadFactory线程工厂一般设为默认值不用改
阻塞队列-----四组api
线程池 4 大策略, 超过 maximumPoolSize + 阻塞队列=线程最大承载时触发,线程数不达到最大承载时不会执行4个策略
以下是4个策略分别执行的操作 1.AbortPolicy 报错 concurrent.RejectedExecutionException 2.CallerRunsPolicy 哪来的去哪里,若为主线程,打发到 main 线程 3.DiscardOldestPolicy 即使线程数超过最大承载,也不会抛出异常,丢掉任务 4.DiscardPolicy 队列满了尝试会与最早的线程竞争,同时不会抛出异常
Running状态下添加处理线程
Shutdown状态下不再接受新的线程,但仍会处理阻塞队列和线程池中的线程
Stop状态下会中断正在处理的线程,不处理阻塞队列和其他
Tidying状态下所有线程执行完毕,ctl记录的线程数为0
Terminated状态下线程池终止
最后简单介绍一下
池的最大大小如何设置(即maximumPoolSize参数的设置) 1. CPU 密集型,电脑或者处理器是几核就设置为几,保持cpu效率最高====如我的电脑为6核12线程(设为12)
动态获取:
Runtime.getRuntime().availableProcessors()2. IO 密集型 根据 十分占用 io 资源的任务数决定。一般设为 2倍 密集任务数
