线程池:三大方法,七大参数,四种拒绝策略

池化技术

当程序允许时需要的链接如:JDBC链接,IO链接等等他们开启或关闭会极大的耗费资源,这时则引入了一个池化技术的概念。
池化技术本质:事先准备好一些资源,要用的时候来这里取,用完了在放回去,这样就不用一直开启关闭浪费资源了。

线程池的好处

  • 降低资源消耗
  • 效率大大提升
  • 方便我们管理

线程复用可以控制最大并发数,管理线程!

线程池三大方法

  1. package JUC.Queue;
  2. import java.util.concurrent.ExecutorService;
  3. import java.util.concurrent.Executors;
  4. /**
  5. * 三大方法
  6. */
  7. public class TestExecutors {
  8. public static void main(String[] args) {
  9. // ExecutorService executorService = Executors.newSingleThreadExecutor();//单个线程
  10. // ExecutorService executorService = Executors.newFixedThreadPool(100);//固定线程池大写
  11. ExecutorService executorService = Executors.newCachedThreadPool();//可伸缩的线程池
  12. try {
  13. for (int i = 0; i < 100; i++) {
  14. executorService.execute(()->{
  15. System.out.println(Thread.currentThread().getName());
  16. });
  17. }
  18. } finally {
  19. //线程池用完一定要关闭
  20. executorService.shutdown();
  21. }
  22. }
  23. }

七大参数

源码分析:

  1. //单个线程
  2. public static ExecutorService newSingleThreadExecutor() {
  3. return new FinalizableDelegatedExecutorService
  4. (new ThreadPoolExecutor(1, 1,
  5. 0L, TimeUnit.MILLISECONDS,
  6. new LinkedBlockingQueue<Runnable>()));
  7. }
  8. //固定线程池大写
  9. public static ExecutorService newFixedThreadPool(int nThreads) {
  10. return new ThreadPoolExecutor(nThreads, nThreads,
  11. 0L, TimeUnit.MILLISECONDS,
  12. new LinkedBlockingQueue<Runnable>());
  13. }
  14. //可伸缩的线程池
  15. public static ExecutorService newCachedThreadPool() {
  16. return new ThreadPoolExecutor(0, Integer.MAX_VALUE, //这里最大核心线程约为21亿!
  17. 60L, TimeUnit.SECONDS,
  18. new SynchronousQueue<Runnable>());
  19. }
  20. //本质开启线程池调用了ThreadPoolExecutor()
  21. public ThreadPoolExecutor(int corePoolSize, //核心线程池大小
  22. int maximumPoolSize, //最大核心线程池大小
  23. long keepAliveTime, //超时了没有人调用就会释放
  24. TimeUnit unit, //超时单位
  25. BlockingQueue<Runnable> workQueue, //阻塞队列
  26. ThreadFactory threadFactory, //线程工厂,创建线程的,一般不动用
  27. RejectedExecutionHandler handler) { //拒绝策略
  28. if (corePoolSize < 0 ||
  29. maximumPoolSize <= 0 ||
  30. maximumPoolSize < corePoolSize ||
  31. keepAliveTime < 0)
  32. throw new IllegalArgumentException();
  33. if (workQueue == null || threadFactory == null || handler == null)
  34. throw new NullPointerException();
  35. this.corePoolSize = corePoolSize;
  36. this.maximumPoolSize = maximumPoolSize;
  37. this.workQueue = workQueue;
  38. this.keepAliveTime = unit.toNanos(keepAliveTime);
  39. this.threadFactory = threadFactory;
  40. this.handler = handler;
  41. }

阿里规范手册!

image.png
image.png

手动创建一个线程池

  1. package JUC.Queue;
  2. import java.util.concurrent.*;
  3. public class TestThreadPoolExecutor {
  4. public static void main(String[] args) {
  5. /**
  6. * 四种拒绝策略
  7. * 1.new ThreadPoolExecutor.AbortPolicy() //线程满了还有线程要进入则,不做处理,直接抛出异常
  8. * 2.new ThreadPoolExecutor.CallerRunsPolicy() //那来的那里去
  9. * 3.new ThreadPoolExecutor.DiscardPolicy() //队列满了丢掉任务,直接开摆,不会抛出异常!
  10. * 4.new ThreadPoolExecutor.DiscardOldestPolicy() //队列满了,尝试去和最早的竞争,也不会抛出异常!
  11. */
  12. ThreadPoolExecutor executor = new ThreadPoolExecutor(
  13. 2,
  14. 5,
  15. 2,
  16. TimeUnit.SECONDS,
  17. new LinkedBlockingQueue<>(3),
  18. Executors.defaultThreadFactory(),
  19. new ThreadPoolExecutor.CallerRunsPolicy());//队列满了,尝试去和最早的竞争,也不会抛出异常!
  20. for (int i = 0; i < 19; i++) {
  21. executor.execute(()->{
  22. System.out.println(Thread.currentThread().getName()+"线程");
  23. });
  24. }
  25. }
  26. }

四种拒绝策略

  1. new ThreadPoolExecutor.AbortPolicy() //线程满了还有线程要进入则,不做处理,直接抛出异常
  2. new ThreadPoolExecutor.CallerRunsPolicy() //那来的那里去
  3. new ThreadPoolExecutor.DiscardPolicy() //队列满了丢掉任务,直接开摆,不会抛出异常!
  4. new ThreadPoolExecutor.DiscardOldestPolicy() //队列满了,尝试去和最早的竞争,也不会抛出异常!

小结和拓展:

池的最大的线程如何去设置?

了解:IO密集型与CPU密集型

  1. package JUC.Queue;
  2. import java.util.concurrent.*;
  3. public class TestThread {
  4. public static void main(String[] args) {
  5. /**
  6. * 最大线程到底该如何定义?
  7. * CPU密集型:CPU几核就是几 可以使用Runtime.getRuntime().availableProcessors()方法检测出电脑是几核的
  8. * IO密集型:判断程序中十分消耗资源的IO有多少个最大线程数大于它就好了(最好是它的两倍)
  9. */
  10. new ThreadPoolExecutor(1,
  11. Runtime.getRuntime().availableProcessors(),
  12. 1,
  13. TimeUnit.SECONDS,
  14. new LinkedBlockingQueue<>(3),
  15. Executors.defaultThreadFactory(),
  16. new ThreadPoolExecutor.DiscardPolicy());
  17. }
  18. }