线程池(重点)
一:线程池:三大方法,七大参数,四种拒绝策略
池化技术:
01:程序的运行,本质 :占用系统的资源! 优化资源的使用! =>池化技术
02:线程池、连接池、内存池、对象池///......创建、销毁。 十分浪费资源
03:池化技术:事先准备好一些资源,有人要用,就来我这里拿,用完之后还给我。
线程池的好处:
01:降低资源的消耗
02:提高响应的速度
03:方便管理
(重点)线程复用、可以控制最大并发数、管理线程
二:三大方法:
01:Executors.newSingleThreadExecutor() //单个线程
代码示例01
1 package pool; 2 3 import java.util.concurrent.ExecutorService; 4 import java.util.concurrent.Executors; 5 6 //Executors 工具类、3大方法 7 8 public class Demo01 { 9 public static void main(String[] args) { 10 11 ExecutorService threadpool = Executors.newSingleThreadExecutor(); //单个线程 12 13 try { 14 for (int i = 0; i < 10; i++) { 15 //使用了线程池之后,使用线程池来创建线程 16 threadpool.execute(()->{ 17 System.out.println(Thread.currentThread().getName()+" ok"); 18 }); 19 } 20 } catch (Exception e) { 21 e.printStackTrace(); 22 } finally { 23 //线程池用完,程序结束,关闭线程池 24 threadpool.shutdown(); //(为确保关闭,将关闭方法放入到finally中) 25 } 26 } 27 }
运行结果: (10个任务被同一个线程所操作)
02:newFixedThreadPool(int nThreads) //创建一个固定的线程池的大小
代码示例02
1 package pool; 2 3 import java.util.concurrent.ExecutorService; 4 import java.util.concurrent.Executors; 5 6 //Executors 工具类、3大方法 7 8 public class Demo01 { 9 public static void main(String[] args) { 10 11 //最多5个线程同时执行,从控制台中查看结果 12 ExecutorService threadpool = Executors.newFixedThreadPool(5); //创建一个固定的线程池的大小,(5个线程) 13 14 try { 15 for (int i = 0; i < 10; i++) { 16 //使用了线程池之后,使用线程池来创建线程 17 threadpool.execute(()->{ 18 System.out.println(Thread.currentThread().getName()+" ok"); 19 }); 20 } 21 } catch (Exception e) { 22 e.printStackTrace(); 23 } finally { 24 //线程池用完,程序结束,关闭线程池 25 threadpool.shutdown(); //(为确保关闭,将关闭方法放入到finally中) 26 } 27 } 28 }
运行结果:(最高同时有5个线程在执行)
03:newCachedThreadPool() //缓存池,可伸缩的, 遇强则强,遇弱则弱
代码示例03
1 package pool; 2 3 import java.util.concurrent.ExecutorService; 4 import java.util.concurrent.Executors; 5 6 //Executors 工具类、3大方法 7 8 public class Demo01 { 9 public static void main(String[] args) { 10 11 ExecutorService threadpool = Executors.newCachedThreadPool(); //缓存池,可伸缩的, 遇强则强,遇弱则弱 12 13 try { 14 for (int i = 0; i < 10; i++) { 15 //使用了线程池之后,使用线程池来创建线程 16 threadpool.execute(()->{ 17 System.out.println(Thread.currentThread().getName()+" ok"); 18 }); 19 } 20 } catch (Exception e) { 21 e.printStackTrace(); 22 } finally { 23 //线程池用完,程序结束,关闭线程池 24 threadpool.shutdown(); //(为确保关闭,将关闭方法放入到finally中) 25 } 26 } 27 }
运行结果:(最高同时有10个线程在执行,可伸缩的, 遇强则强,遇弱则弱)
三:七大参数
01:三大方法之源码分析:
1 (1) newSingleThreadExecutor() //单个线程 2 3 public static ExecutorService newSingleThreadExecutor() { 4 return new FinalizableDelegatedExecutorService 5 (new ThreadPoolExecutor(1, 1, 6 0L, TimeUnit.MILLISECONDS, 7 new LinkedBlockingQueue<Runnable>())); 8 } 9 ================================================================================== 10 (2) newFixedThreadPool(int nThreads) //创建一个固定的线程池的大小 11 12 public static ExecutorService newFixedThreadPool(int nThreads) { 13 return new ThreadPoolExecutor(nThreads, nThreads, 14 0L, TimeUnit.MILLISECONDS, 15 new LinkedBlockingQueue<Runnable>()); 16 } 17 =================================================================================== 18 (3) newCachedThreadPool() //缓存池,可伸缩的, 遇强则强,遇弱则弱 19 20 public static ExecutorService newCachedThreadPool() { 21 return new ThreadPoolExecutor(0, Integer.MAX_VALUE, //Integer.Max_VALUE 约等于21亿 //如果我们有这么多条线程一起跑的话,电脑会OOM(溢出),出现问题 22 60L, TimeUnit.SECONDS, 23 new SynchronousQueue<Runnable>()); 24 } 25 ==================================================================================== 26 (4) 三大方法所公共的 ThreadPoolExecutor() 方法 27 28 ******7大参数****** 29 30 public ThreadPoolExecutor(int corePoolSize, //核心线程池大小 31 int maximumPoolSize, //最大核心线程池大小 32 long keepAliveTime, //超时了没有人调用就会释放 33 TimeUnit unit, //超时单位 34 BlockingQueue<Runnable> workQueue, //阻塞队列 35 ThreadFactory threadFactory, //线程工厂,创建线程的,一般不用动 36 RejectedExecutionHandler handler) { //拒绝策略 37 if (corePoolSize < 0 || 38 maximumPoolSize <= 0 || 39 maximumPoolSize < corePoolSize || 40 keepAliveTime < 0) 41 throw new IllegalArgumentException(); 42 if (workQueue == null || threadFactory == null || handler == null) 43 throw new NullPointerException(); 44 this.corePoolSize = corePoolSize; 45 this.maximumPoolSize = maximumPoolSize; 46 this.workQueue = workQueue; 47 this.keepAliveTime = unit.toNanos(keepAliveTime); 48 this.threadFactory = threadFactory; 49 this.handler = handler; 50 }
阿里巴巴开发手册中有如下规定:
例如银行办理业务图:
四:四种拒绝策略:
/**
* new ThreadPoolExecutor.AbortPolicy() //银行满了,还有人进来,不处理这个人的,抛出异常
* new ThreadPoolExecutor.CallerRunsPolicy() //哪来的去哪里!
* new ThreadPoolExecutor.DiscardPolicy() //队列满了,丢掉任务,不会抛出异常!
* new ThreadPoolExecutor.DiscardOldestPolicy() //队列满了,尝试和最早的竞争,也不会抛出异常
*/
五:手动(自定义)创建一个线程池:
代码示例01 new ThreadPoolExecutor.AbortPolicy() //银行满了,还有人进来,不处理这个人的,抛出异常
1 package 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 Demo02 { 9 public static void main(String[] args) { 10 //自定义线程池! 工作中只会使用 ThreadPoolExecutor 11 ThreadPoolExecutor threadPool = new ThreadPoolExecutor( 12 2, //核心线程池大小 13 5, //最大核心线程池大小 14 3, //超时了没有人调用就会释放 15 TimeUnit.SECONDS, //超时单位 16 new LinkedBlockingDeque<>(3), //阻塞队列 17 Executors.defaultThreadFactory(), //线程工厂,创建线程的,一般不用动 18 new ThreadPoolExecutor.AbortPolicy()); //银行满了,还有人进来,不处理这个人的,抛出异常 19 20 try { 21 //最大承载数,Deque + Max (队列线程数+最大线程数) 22 //超出 抛出 RejectedExecutionException 异常 23 for (int i = 1; i <= 9; i++) { 24 //使用了线程池之后,使用线程池来创建线程 25 threadPool.execute(()->{ 26 System.out.println(Thread.currentThread().getName()+" ok"); 27 }); 28 } 29 } catch (Exception e) { 30 e.printStackTrace(); 31 } finally { 32 //线程池用完,程序结束,关闭线程池 33 threadPool.shutdown(); //(为确保关闭,将关闭方法放入到finally中) 34 } 35 } 36 }
运行结果(对比):
代码示例02 new ThreadPoolExecutor.CallerRunsPolicy() //哪来的去哪里
1 package 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 Demo02 { 9 public static void main(String[] args) { 10 //自定义线程池! 工作中只会使用 ThreadPoolExecutor 11 ThreadPoolExecutor threadPool = new ThreadPoolExecutor( 12 2, //核心线程池大小 13 5, //最大核心线程池大小 14 3, //超时了没有人调用就会释放 15 TimeUnit.SECONDS, //超时单位 16 new LinkedBlockingDeque<>(3), //阻塞队列 17 Executors.defaultThreadFactory(), //线程工厂,创建线程的,一般不用动 18 new ThreadPoolExecutor.CallerRunsPolicy()); //哪来的去哪里! 19 20 try { 21 //最大承载数,Deque + Max (队列线程数+最大线程数) 22 //超出 抛出 RejectedExecutionException 异常 23 for (int i = 1; i <= 9; i++) { 24 //使用了线程池之后,使用线程池来创建线程 25 threadPool.execute(()->{ 26 System.out.println(Thread.currentThread().getName()+" ok"); 27 }); 28 } 29 } catch (Exception e) { 30 e.printStackTrace(); 31 } finally { 32 //线程池用完,程序结束,关闭线程池 33 threadPool.shutdown(); //(为确保关闭,将关闭方法放入到finally中) 34 } 35 } 36 }
运行结果:
代码示例03 new ThreadPoolExecutor.DiscardPolicy() //队列满了,丢掉任务,不会抛出异常!
1 package 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 Demo02 { 9 public static void main(String[] args) { 10 //自定义线程池! 工作中只会使用 ThreadPoolExecutor 11 ThreadPoolExecutor threadPool = new ThreadPoolExecutor( 12 2, //核心线程池大小 13 5, //最大核心线程池大小 14 3, //超时了没有人调用就会释放 15 TimeUnit.SECONDS, //超时单位 16 new LinkedBlockingDeque<>(3), //阻塞队列 17 Executors.defaultThreadFactory(), //线程工厂,创建线程的,一般不用动 18 new ThreadPoolExecutor.DiscardPolicy()); //队列满了,丢掉任务,不会抛出异常! 19 20 try { 21 //最大承载数,Deque + Max (队列线程数+最大线程数) 22 //超出 抛出 RejectedExecutionException 异常 23 for (int i = 1; i <= 9; i++) { 24 //使用了线程池之后,使用线程池来创建线程 25 threadPool.execute(()->{ 26 System.out.println(Thread.currentThread().getName()+" ok"); 27 }); 28 } 29 } catch (Exception e) { 30 e.printStackTrace(); 31 } finally { 32 //线程池用完,程序结束,关闭线程池 33 threadPool.shutdown(); //(为确保关闭,将关闭方法放入到finally中) 34 } 35 } 36 }
运行结果:
04:代码示例 new ThreadPoolExecutor.DiscardOldestPolicy() //队列满了,尝试和最早的竞争,也不会抛出异常
1 package 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 Demo02 { 9 public static void main(String[] args) { 10 //自定义线程池! 工作中只会使用 ThreadPoolExecutor 11 ThreadPoolExecutor threadPool = new ThreadPoolExecutor( 12 2, //核心线程池大小 13 5, //最大核心线程池大小 14 3, //超时了没有人调用就会释放 15 TimeUnit.SECONDS, //超时单位 16 new LinkedBlockingDeque<>(3), //阻塞队列 17 Executors.defaultThreadFactory(), //线程工厂,创建线程的,一般不用动 18 new ThreadPoolExecutor.DiscardOldestPolicy()); //队列满了,尝试和最早的竞争,也不会抛出异常 19 20 try { 21 //最大承载数,Deque + Max (队列线程数+最大线程数) 22 //超出 抛出 RejectedExecutionException 异常 23 for (int i = 1; i <= 9; i++) { 24 //使用了线程池之后,使用线程池来创建线程 25 threadPool.execute(()->{ 26 System.out.println(Thread.currentThread().getName()+" ok"); 27 }); 28 } 29 } catch (Exception e) { 30 e.printStackTrace(); 31 } finally { 32 //线程池用完,程序结束,关闭线程池 33 threadPool.shutdown(); //(为确保关闭,将关闭方法放入到finally中) 34 } 35 } 36 }
运行结果: