2022.8.21 线程池
11、线程池(重点)
线程池 Executors:3大方法、7大参数、4种拒绝策略
池化技术
程序的运行,本质:占用系统的资源!优化资源的使用! ==> 引进了一种技术池化池
线程池、连接池、内存池、对象池…
池化技术:事先准备好一些资源,有人要用,就来我这里拿,用完之后还给我。
线程池的好处
1、降低资源的消耗
2、提高响应的速度
3、方便管理
线程可以复用、可以控制最大并发数、管理线程
三大方法
单个线程
1 package com.xing.pool; 2 3 import java.util.concurrent.ExecutorService; 4 import java.util.concurrent.Executors; 5 //Executors 工具类 三大方法 6 public class Test01 { 7 public static void main(String[] args) { 8 //这个线程池只有一个线程处理 9 ExecutorService threadpool = Executors.newSingleThreadExecutor(); 10 11 try{ 12 for(int i =1;i < 10; i++){ 13 //使用了线程池之后,使用线程池来创建线程 14 threadpool.execute(()->{ 15 System.out.println(Thread.currentThread().getName() + "OK" ); 16 }); 17 } 18 }catch (Exception e){ 19 e.printStackTrace(); 20 }finally { 21 //程序结束要停止线程池 22 threadpool.shutdown(); 23 } 24 25 } 26 } 27
创建一个固定先线程池的大小
1 package com.xing.pool; 2 3 import java.util.concurrent.ExecutorService; 4 import java.util.concurrent.Executors; 5 //Executors 工具类 三大方法 6 public class Test01 { 7 public static void main(String[] args) { 8 //创建一个固定的线程池的大小 最多5个线程并发 9 ExecutorService threadpool = Executors.newFixedThreadPool(5); 10 11 12 try{ 13 for(int i =1;i < 10; i++){ 14 //使用了线程池之后,使用线程池来创建线程 15 threadpool.execute(()->{ 16 System.out.println(Thread.currentThread().getName() + "==>OK" ); 17 }); 18 } 19 }catch (Exception e){ 20 e.printStackTrace(); 21 }finally { 22 //程序结束要停止线程池 23 threadpool.shutdown(); 24 } 25 26 } 27 } 28
1 package com.xing.pool; 2 3 import java.util.concurrent.ExecutorService; 4 import java.util.concurrent.Executors; 5 //Executors 工具类 三大方法 6 public class Test01 { 7 public static void main(String[] args) { 8 //可伸缩的缓存 9 ExecutorService threadpool = Executors.newCachedThreadPool(); 10 try{ 11 for(int i =1;i < 10; i++){ 12 //使用了线程池之后,使用线程池来创建线程 13 threadpool.execute(()->{ 14 System.out.println(Thread.currentThread().getName() + "==>OK" ); 15 }); 16 } 17 }catch (Exception e){ 18 e.printStackTrace(); 19 }finally { 20 //程序结束要停止线程池 21 threadpool.shutdown(); 22 } 23 24 } 25 } 26
三大方法源码
1 public static ExecutorService newSingleThreadExecutor() { 2 return new FinalizableDelegatedExecutorService 3 (new ThreadPoolExecutor(1, 1, 4 0L, TimeUnit.MILLISECONDS, 5 new LinkedBlockingQueue<Runnable>())); 6 } 7 8 public static ExecutorService newFixedThreadPool(int nThreads) { 9 return new ThreadPoolExecutor(nThreads, nThreads, 10 0L, TimeUnit.MILLISECONDS, 11 new LinkedBlockingQueue<Runnable>()); 12 } 13 public static ExecutorService newCachedThreadPool() { 14 return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 15 60L, TimeUnit.SECONDS, 16 new SynchronousQueue<Runnable>()); 17 }
这里看出都new了一个ThreadPoolExecutor的类,点击进去看他的源码
1 //有7个参数 7大参数 2 public ThreadPoolExecutor(int corePoolSize,//核心线程池大小 3 //核心线程池不够时 “增加线程池大小” 4 int maximumPoolSize,//最大的线程池大小 5 long keepAliveTime,//“增加的线程池”存活的时间,超时无人调用就会释放 6 TimeUnit unit,//超时的单位 7 BlockingQueue<Runnable> workQueue,//阻塞队列 8 ThreadFactory threadFactory,//创建线程的工厂,一般不用动 9 RejectedExecutionHandler handler) {//拒绝策略 10 if (corePoolSize < 0 || 11 maximumPoolSize <= 0 || 12 maximumPoolSize < corePoolSize || 13 keepAliveTime < 0) 14 throw new IllegalArgumentException(); 15 if (workQueue == null || threadFactory == null || handler == null) 16 throw new NullPointerException(); 17 this.acc = System.getSecurityManager() == null ? 18 null : 19 AccessController.getContext(); 20 this.corePoolSize = corePoolSize; 21 this.maximumPoolSize = maximumPoolSize; 22 this.workQueue = workQueue; 23 this.keepAliveTime = unit.toNanos(keepAliveTime); 24 this.threadFactory = threadFactory; 25 this.handler = handler; 26 }
七大参数
4种拒绝策略
1 package com.xing.pool; 2 3 import java.util.concurrent.*; 4 5 public class Test01 { 6 public static void main(String[] args) { 7 8 //自定义线程池 9 ExecutorService threadpool = new ThreadPoolExecutor(2, //默认处理口数,目前银行开放的窗口数 10 5, //最大处理口数,人数太多了 将开放的窗口数增加到5个 11 3,//超出空闲时间除了默认线程数其他都释放 超过3秒钟额外开放的5-2=3个窗口没人用就会关闭 12 TimeUnit.SECONDS,//时间单位 13 new LinkedBlockingDeque<>(3),//提供等待区的队列 候客区最多3个人 14 Executors.defaultThreadFactory(),//一般不会变,默认线程模式 15 new ThreadPoolExecutor.AbortPolicy()//拒绝策略,开放到5个窗口也不够用的话,多余的人执行的策略 16 // new ThreadPoolExecutor.AbortPolicy());//拒绝策列的一种,服务口和等待队列都满了的时候,还有人进来,抛出异常 17 // new ThreadPoolExecutor.CallerRunsPolicy());//哪来的回哪去(main处理) 比如你爸爸 让你去通知妈妈洗衣服,妈妈拒绝,让你回去通知爸爸洗 18 // new ThreadPoolExecutor.DiscardPolicy());//拒绝策列的一种,会丢掉多余的任务,不会抛出异常 19 // new ThreadPoolExecutor.DiscardOldestPolicy());//拒绝策列的一种,服务口和等待队列都满了的时候,后面进来的人会尝试去和第一个竞争,不会抛出异常 20 ); 21 try{ 22 //最大承载线程数:LinkedBlockingDeque + 最大处理口数 3+5=8 同时处理8个线程时,到达最大处理口数 23 // RejectedExecutionException 超出最大承载异常 24 /* 25 * 同时处理5个人 2个人去窗口,3个人候客厅,开启窗口数达到3 26 * 6 2 3 3,最大线程被触发 27 * 7 2 3 4,最大线程被触发 28 * 8 2 3 5,最大线程被触发,达到最大承载线程数 29 * 9 2 3 5,最大线程被触发,达到最大承载线程数,根据拒绝策略处理此线程 30 * 31 */ 32 for(int i =1;i < 10; i++){ 33 //使用了线程池之后,使用线程池来创建线程 34 threadpool.execute(()->{ 35 System.out.println(Thread.currentThread().getName() + "==>OK" ); 36 }); 37 } 38 }catch (Exception e){ 39 e.printStackTrace(); 40 }finally { 41 //程序结束要停止线程池 42 threadpool.shutdown(); 43 } 44 45 } 46 } 47
最大线程数如何定义
-
cpu 密集型 ,几核,就是几,可以保持cpu的效率最高
-
IO 密集型 > 判断你的程序中十分消耗IO的线程 一般设置为2倍
-
假如程序有15个大型任务,io十分占用资源 设置为30
-
1 package com.xing.pool; 2 3 import java.util.concurrent.Executors; 4 import java.util.concurrent.LinkedBlockingDeque; 5 import java.util.concurrent.ThreadPoolExecutor; 6 import java.util.concurrent.TimeUnit; 7 8 public class Test02 { 9 public static void main(String[] args) { 10 最大线程数如何定义 11 12 13 //自定义线程池 14 System.out.println(Runtime.getRuntime().availableProcessors());//获取cpu的核数 15 ThreadPoolExecutor executorService = new ThreadPoolExecutor( 16 2,//默认处理口数 17 Runtime.getRuntime().availableProcessors(),//最大处理口数 cpu核数 18 3,//超出空闲时间除了默认线程数其他都释放 19 TimeUnit.SECONDS,//时间单位 20 new LinkedBlockingDeque<>(3),//提供等待区的队列 21 Executors.defaultThreadFactory(),//一般不会变,默认线程模式 22 new ThreadPoolExecutor.AbortPolicy());//拒绝策列的一种,服务口和等待队列都满了的时候,还有人进来,抛出异常 23 try { 24 for (int i = 0; i < 9; i++) { 25 executorService.execute(()->{ 26 System.out.println(Thread.currentThread().getName() + "ok"); 27 }); 28 } 29 } catch (Exception e) { 30 e.printStackTrace(); 31 }finally { 32 executorService.shutdown(); 33 } 34 } 35 }