线程池:三大方法、7大参数、4种拒绝策略
几个重点:
一个线程池的最多可以接受线程数:最大承载:队列数量+ max线程数。来一个任务的步骤是这样的,先消费核心的线程数,然后进队列,然后再消费max线程数。再来的话,就该走拒绝策略了。
池化技术
程序的运行,本质:占用系统的资源! 优化资源的使用!=>池化技术 线程池、连接池、内存池、对象池///….. 创建、销毁。十分浪费资源 池化技术:事先准备好一些资源,有人要用,就来我这里拿,用完之后还给我。
线程池的好处:
1、降低资源的消耗
2、提高响应的速度
3、方便管理。
线程复用、可以控制最大并发数、管理线程
线程池:三大方法
线程池创建的三种方法。但是我们一般不用,一般我们用原生的创建,因为更可控。
阿里巴巴java手册也不推荐我们使用Executors来创建线程池,可能会导致OOM
import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;// Executors 工具类、3大方法public class Demo01 {public static void main(String[] args) {ExecutorService threadPool = Executors.newSingleThreadExecutor();// 单个线程// ExecutorService threadPool = Executors.newFixedThreadPool(5); // 创建一个固定的线程池的大小// ExecutorService threadPool = Executors.newCachedThreadPool(); // 可伸缩的,遇强则强,遇弱则弱try {for (int i = 0; i < 100; i++) {// 使用了线程池之后,使用线程池来创建线程threadPool.execute(() -> {System.out.println(Thread.currentThread().getName() + " ok");});}} catch (Exception e) {e.printStackTrace();} finally {// 线程池用完,程序结束,关闭线程池threadPool.shutdown();}}}
线程池:7大参数
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.acc = System.getSecurityManager() == null ?null :AccessController.getContext();this.corePoolSize = corePoolSize;this.maximumPoolSize = maximumPoolSize;this.workQueue = workQueue;this.keepAliveTime = unit.toNanos(keepAliveTime);this.threadFactory = threadFactory;this.handler = handler;}

手动创建一个线程池
import java.util.ArrayList;import java.util.List;import java.util.concurrent.*;// Executors 工具类、3大方法/*** new ThreadPoolExecutor.AbortPolicy() // 银行满了,还有人进来,不处理这个人的,抛出异常* new ThreadPoolExecutor.CallerRunsPolicy() // 哪来的去哪里!* new ThreadPoolExecutor.DiscardPolicy() //队列满了,丢掉任务,不会抛出异常!* new ThreadPoolExecutor.DiscardOldestPolicy() //队列满了,尝试去和最早的竞争,也不会抛出异常!*/public class Demo01 {public static void main(String[] args) {// 自定义线程池!工作 ThreadPoolExecutor// 最大线程到底该如何定义// 1、CPU 密集型,几核,就是几,可以保持CPu的效率最高!// 2、IO 密集型 > 判断你程序中十分耗IO的线程,// 程序 15个大型任务 io十分占用资源!// 获取CPU的核数System.out.println(Runtime.getRuntime().availableProcessors());List list = new ArrayList();ExecutorService threadPool = new ThreadPoolExecutor(2,Runtime.getRuntime().availableProcessors(),3,TimeUnit.SECONDS,new LinkedBlockingDeque<>(3),Executors.defaultThreadFactory(),new ThreadPoolExecutor.DiscardOldestPolicy()); //队列满了,尝试去和最早的竞争,也不会抛出异常!try {// 最大承载:Deque + max// 超过 RejectedExecutionExceptionfor (int i = 1; i <= 9; i++) {// 使用了线程池之后,使用线程池来创建线程threadPool.execute(()->{System.out.println(Thread.currentThread().getName()+" ok");});}} catch (Exception e) {e.printStackTrace();} finally {// 线程池用完,程序结束,关闭线程池threadPool.shutdown();}}}
4种拒绝策略
/*** new ThreadPoolExecutor.AbortPolicy() // 银行满了,还有人进来,不处理这个人的,抛出异常* new ThreadPoolExecutor.CallerRunsPolicy() // 哪来的去哪里!* new ThreadPoolExecutor.DiscardPolicy() //队列满了,丢掉任务,不会抛出异常!* new ThreadPoolExecutor.DiscardOldestPolicy() //队列满了,尝试去和最早的竞争,也不会抛出异常!*/
小结和拓展
池的最大的大小如何去设置!
了解:IO密集型,CPU密集型:(调优)
到底我们实际生产中要造几个线程的线程池呢???
如果我们的项目中 是cpu密集型的(就是处理业务的多,没有跟磁盘读取打交道的)那线程数量就用
System.out.println(Runtime.getRuntime().availableProcessors());
得到的是当前电脑的核心数。
如果是io读取比较多的话,打个比方说项目中大概有10个需要io操作的业务,那我们通常是*2。也就是最多20个线程。
