Java线程池学习笔记

Java线程池学习笔记

1.线程池

  1. 线程的创建和销毁需要一定的开销;
  2. 需要线程池对线程进行管理,减少资源的耗费;
  3. Executor框架将任务的创建和执行进行解耦:Runnable和Callable进行任务的创建,ThreadPoolExecutor用于执行任务;

1.1.Executor

execute和submit
  1. execute适用于"触发就忘"的场景,submit适合需要获取结果或控制任务状态的场景;
  2. submit的返回值是Future,可以通过Future检查任务是否完成,取消任务, 获取阻塞等待结果,执行到异常时不会立即抛出,在get方法会抛出异常

2.ThreadPoolExecutor

2.1.构造方法

java 复制代码
public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          ThreadFactory threadFactory,
                          RejectedExecutionHandler handler)
  1. corePoolSize:核心线程数;调用prestartAllcoreThread会启动所有核心线程;

  2. maximumPoolSize:最大线程数;

  3. keepAliveTime:非核心线程超时回收时间;调用allowCoreThreadTimeout为true,超时回收也会应用到核心线程上;

  4. unit:上面参数的时间单位;

  5. workQueue:任务队列;

  6. threadFactory:线程工厂;作用:给创建的线程设置名字,代码:

    java 复制代码
     // 创建线程工厂,用于给线程命名
        ThreadFactory threadFactory = new ThreadFactory() {
            private final AtomicInteger threadNumber = new AtomicInteger(1);
            
            @Override
            public Thread newThread(Runnable r) {
                Thread t = new Thread(r, "MyThread-" + threadNumber.getAndIncrement());
                return t;
            }
        };
  7. RejectedExecutionHandler:饱和策略;当任务队列和线程数都满了时执行的策略,默认AbortPolicy:无法处理新任务,并抛出RejectedExecutionException异常;此外还有三种策略:

    1. CallerRunsPolicy:用调用者所在线程执行任务;
    2. DiscardPolicy:丢弃待执行的任务;
    3. DiscardOldestPolicy:丢弃队列中最早进入队列的任务(队列的头),执行当前任务

2.2.线程池执行顺序

  1. 启动核心线程
  2. 核心线程满了,加入任务队列
  3. 任务队列满了,启动非核心线程,数量不能超过最大线程数-核心线程数
  4. 执行饱和策略

3.线程池种类

3.1.Executors.newFixedThreadPool

  1. 实现:new ThreadPoolExecutor(n,n,0,TimeUnit.MILLISECONDS,new LinkedBlockingQueue())
  2. 工作流程:启动核心线程,核心线程满了加入任务队列,核心线程运行完取出任务执行
  3. 没有超时回收,因为没有非核心线程

3.2.Executors.newCachedThreadPool

  1. 实现:new ThreadPoolExecutor(0,Integer.MAX_VALUE,60,TimeUnit.SECONDS,new SynchronousQueue())
  2. 工作流程:加入任务队列,SynchronousQueue不支持存放元素,存储一个任务就需要移除它,所以要创建一个非核心线程取出任务进行执行,执行任务时如果有空闲线程就不创建新线程,反之需要创建
  3. 线程执行完任务空闲60s没有任务过来超时回收

3.3.Executors.newSingleThreadExecutor

  1. 实现:new ThreadPoolExecutor(1,1,0,TimeUnit.MILLISECONDS,new LinkedBlocking())
  2. 工作流程:创建核心线程,添加到任务队列,取出任务队列执行
  3. 特点:单个线程按顺序执行任务

3.4.Executors.newScheduledThreadPool

  1. 实现:new ThreadPoolExecutor(n,Integer.MAX_VALUE,DEFAULT_KEEPALIVE_MILLISSECONDS,TimeUnit.MILLISECONDS,new DelayedWorkQueue())

  2. 工作流程:创建核心线程,放入队列等待核心线程空闲,因为DelayedWorkQueue无界,基本不会创建非核心线程

  3. 常用API:

    • schedule:延时执行
    java 复制代码
    ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);
    
    // 场景1:3秒后发送一条通知
    scheduler.schedule(() -> {
        System.out.println("3秒到了,发送推送通知");
    }, 3, TimeUnit.SECONDS);
    • scheduleAtFixedRate:固定频率执行
    java 复制代码
    // 场景2:每5秒检查一次网络状态(不管任务执行多久)
    scheduler.scheduleAtFixedRate(() -> {
       System.out.println("检查网络连接状态...");
       // 假设这个检查需要2秒
    }, 0, 5, TimeUnit.SECONDS);
    // 参数:首次延迟0秒,之后每5秒执行一次
    • scheduleWithFixedDelay:固定延迟执行
    java 复制代码
    	// 场景3:每次请求完成后,等待3秒再进行下一次
    scheduler.scheduleWithFixedDelay(() -> {
        System.out.println("拉取服务器数据...");
        // 假设拉取数据需要2秒
        Thread.sleep(2000);
    }, 0, 3, TimeUnit.SECONDS);
    // 执行流程:拉取(2秒) -> 等待3秒 -> 拉取(2秒) -> 等待3秒...

4.线程池和其他API比较

4.1.Android开发很少用Executors的原因

  1. 生命周期管理复杂

    java 复制代码
    // 容易忘记shutdown,导致内存泄漏
    // 需要在每个Activity的onDestroy中处理,容易遗漏
  2. 有更好的替代方案
    替代方案 优势
    Kotlin Coroutines 自动绑定生命周期,Scope管理
    RxJava 丰富的操作符,自动取消订阅
    WorkManager 系统级任务调度,保证执行
    LiveData + Room 数据库异步查询自动管理

相关推荐
咸鱼2.01 小时前
【java入门到放弃】Dubbo
java·开发语言·dubbo
JAVA面经实录9177 小时前
Java企业级工程化·终极完整版背诵手册(无遗漏、全覆盖、面试+落地通用)
java·开发语言·面试
lilihuigz7 小时前
Tutor LMS 4.0 Beta版全新上线:以学习者为中心的移动优先学习体验
学习·在线教育·lms
William Dawson7 小时前
2026软考中级系统集成项目管理工程师备考笔记
笔记·系统集成项目管理工程师
许彰午9 小时前
CacheSQL(二):主从复制——OpLog 环形缓冲区与故障自动恢复
java·数据库·缓存
Bat U10 小时前
JavaEE|多线程初阶(七)
java·开发语言
love530love10 小时前
精简版|Claude-HUD 插件介绍 + 一键安装教程
人工智能·windows·笔记
kuinnebula10 小时前
RTSP学习
学习
想成为优秀工程师的爸爸11 小时前
第三十篇技术笔记:郭大侠学UDS - 人有生老三千疾,望闻问切良方医
网络·笔记·网络协议·tcp/ip·信息与通信
北顾笙98012 小时前
LLM学习-day04
学习