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 小时前
go语言学习难度及适合学习的人群
开发语言·学习·golang
wangchunyu1144 小时前
JAVA CompletableFuture异步编程实战
java·开发语言·python
paopaokaka_luck5 小时前
流浪动物救助与收养系统(DeepSeek AI对话、 ECharts多维分析、救助流程衔接、领养与回访衔接、 捐赠确认与公示、志愿者协作)
java·前端·javascript·人工智能·mysql·echarts·推荐算法
Thomas.Sir5 小时前
第9课:SpringBoot4.x Web开发基础:WebMvc自动配置、静态资源、请求参数接收
java·spring boot
程序 代码狂人5 小时前
切片表与分区表的区别(数据开发面试版)
java·大数据·开发语言·数据仓库·算法
2501_944521596 小时前
Deepmerge 跨端三方库仓颉适配全流程
java·python·eclipse·github
楚山之石6 小时前
【Medical Image Analysis】深度学习医学图像合成综述:伪CT、合成MRI与合成PET的架构、性能与临床边界
图像处理·人工智能·学习·mr·mri
南归北隐7 小时前
Spring AI Alibaba Graph框架实现MCP数据库查询实战
java·后端·spring ai·mcp·spring ai mcp
古法老登瞎折腾7 小时前
大数据智能运维实战(九):让 AI 查日志——找到异常,也保留上下文
java·大数据·运维·人工智能·spring ai·mcp
Li_RuiQi7 小时前
DAgger方法演进_独立学习笔记
笔记·学习·计算机视觉