• Java使用线程池


    线程池类位于 java.util.concurrent 包

    1. 简介

      ​ Java虽然支持多线程,启动一个新的线程非常简单。但是频繁创建销毁线程需要消耗大量的系统资源(线程资源、栈空间等),更好的做法是使用【线程池】。

      线程池

    2. Java标准库提供ExecutorService接口表示线程池,它的典型用法如下:

      • submit(Runnable runnable)接收实现 Runnable 接口的对象。
      // 创建固定大小的线程池:
      ExecutorService executor = Executors.newFixedThreadPool(3);
      // 提交任务:
      executor.submit(task1);
      executor.submit(task2);
      executor.submit(task3);
      executor.submit(task4);
      executor.submit(task5);
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
    3. 常见的 ExecutorService 接口实现类:

      • FixedThreadPool:线程数固定的线程池。
      • CacheThreadPool:线程数根据任务动态调整线程池,无上限。
      • SingleThreadExecutor:仅单线程执行的线程池。
      • ScheduleThreadPool:定时任务、循环执行。

      (创建这些线程池的方法都被封装到Executors这个类中)

      ExecutorService es = Executors.newFixedThreadPool(4);
      
      • 1
    4. 3种线程池关闭方式

      • .shutdown():等待正在执行的任务先完成,然后再关闭。
      • .shutdownNow():立刻停止正在执行的任务(强制关闭)。
      • .awaitTermination():等待指定的时间后让线程池关闭。
    5. 【必要性说明】:线程池最后需要手动关闭。

      import java.util.concurrent.*;
      
      public class Main {
          public static void main(String[] args) {
              ExecutorService es = Executors.newFixedThreadPool(4);
              for (int i = 0; i < 6; i++) {
                  es.submit(new Task());
              }
              // 关闭线程池:
              es.shutdown();
          }
      }
      
      class Task implements Runnable {
          @Override
          public void run() {
              System.out.println("a");
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
    6. 创建动态线程池

      • 原理:基于 CacheThreadPool 底层源码,创建存在 min 与 max 的线程池。

        • 线程数量:0 ~ 无限大。
        • 每个线程的最长存活时间:60秒。
        • 工作队列为:SynchronousQueue

        image-20220822162648332

        // 创建指定 min 与 max 的线程池
        int min = 4;
        int max = 10;
        ExecutorService es = new ThreadPoolExecutor(min, max,60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>());
        
        • 1
        • 2
        • 3
        • 4
    7. 【小总结】

      • 线程池的使用使得不再需要通过以往的.start()方式启动线程,而是直接将线程置于线程池中即可。
      • CacheThreadPool有存活时间,FixedThreadPool与SingleThreadExecutor没有存活时间(超时时间)。
    8. ScheduleThreadPool【定时任务】

      • 简介:特殊的线程池,定时任务、可以反复执行。

      • 执行类型:

        • FixedRate:任务总是以固定的时间触发,而不管任务执行时间多长。
        • FixedDelay:上一次任务执行完毕后等待固定的时间间隔,再执行下一次任务。

        在这里插入图片描述

      ScheduledExecutorService s=Executors.newScheduledThreadPool(4);
      
      • 1
      // 1秒后执行任务,而且只执行一次。
      ses.schedule(new Task("one-time")1TimeUnit.SECONDS);
      
      • 1
      • 2
      // FixedRate,10秒后开始执行定时任务,每3秒执行。
      ses.scheduleWithFixedRate(new Task(),10,3, TimeUnit.SECONDS);
      
      // FixedDelay,10秒后开始执行定时任务,每3秒执行。
      ses.scheduleWithFixedDelay(new Task(),10,3, TimeUnit.SECONDS);
      
      • 1
      • 2
      • 3
      • 4
      • 5
      // lambda表达式
      ses.schedule(()->{
        
          System.out.PrintLn("hello");
        
      }1TimeUnit.SECONDS);
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
    9. 思考以下问题:

      • 在FixedRate模式下,假设每秒触发,而某次任务的执行时间超过了1s,那么会不会造成并发执行?如果此任务的任何执行时间超过其周期,则后续执行可能会延迟开始,但不会并发执行。
      • 如果任务抛出了异常,那么后续任务会不会继续执行 ?如果任务发生异常,将禁止后续任务执行。
    10. 【Timer】说明:

      Java标准库中海提供了一个java.util.Timer类,这个类也可以执行定时任务,但这个类所代表的是一个旧的体系,并不推荐,Shedule 完全可以代替 Timer。

  • 相关阅读:
    【js基础】逻辑判断篇(易错点)
    猿创征文| 内网穿透工具(全免费)
    自动化数据读取报错元素找不到
    37-5 基于时间的盲注 SQL 注入 PoC 的 Python 编写
    树形Dp 2925. 在树上执行操作以后得到的最大分数
    52.【Java 数据结构——线性表】
    ICMP协议(一)
    mulesoft Module 6 quiz 解析
    力扣.面试题 04.06. 后继者(java 树的中序遍历)
    python+selenium模拟键盘使用ESC退出某个页面中的小页面
  • 原文地址:https://blog.csdn.net/qq_35760825/article/details/126469870