Java学习28

上午 3h 线程池基础概念 + Executors 工具类

1 线程池是什么(0.5h 精讲)

原生问题(不用线程池的弊端)

以前写法:每来一个任务就 new Thread ()

  1. 线程创建、销毁开销极大,浪费 CPU、内存资源
  2. 任务多了会无限创建线程,系统卡顿、OOM 内存溢出
  3. 线程杂乱无章,无法统一管理并发数量

线程池核心定义

提前初始化一批线程 放在「池子」里,复用已有线程 ,不用频繁新建 / 销毁;任务来了直接分配池内空闲线程执行,执行完线程不销毁、回归池里待命

通俗比喻

  • 原生 new Thread:来一个客人招一个临时工,干完就辞退,成本极高
  • 线程池:提前养一批正式员工,来任务就安排员工做,做完员工待命不辞退

2 线程池核心优势(0.3h 必背)

  1. 降低资源消耗:复用线程,避免频繁创建、销毁的系统开销
  2. 提高响应速度:任务到达不用新建线程,直接拿空闲线程立刻执行
  3. 统一管理:控制并发线程数、排队任务、统一关闭、调度管控
  4. 规避无限创建线程:限制最大并发,防止系统崩溃

3 Executors 工具类 + 三种常用线程池(2.2h 精讲 + 完整代码)

前置知识点

Executors:JDK 官方工具类 ,专门快速创建线程池,不用自己底层构造。核心提交任务方法:execute(Runnable任务)

3.1 newFixedThreadPool (int 线程数) 固定数量线程池

特点
  1. 池内线程数量固定不变
  2. 任务多于线程数时,任务进入队列排队
  3. 适合:并发量固定、服务器稳定业务
完整代码 + 逐行解析

java

运行

复制代码
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

// 自定义任务
class MyTask implements Runnable {
    private String name;
    public MyTask(String name) {
        this.name = name;
    }

    @Override
    public void run() {
        // 获取当前执行任务的线程名
        System.out.println(Thread.currentThread().getName() + " 正在执行:" + name);
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + " 完成:" + name);
    }
}

public class FixedThreadPoolDemo {
    public static void main(String[] args) {
        // 1. 创建固定3个线程的线程池
        ExecutorService pool = Executors.newFixedThreadPool(3);

        // 2. 提交5个任务
        for (int i = 1; i <= 5; i++) {
            pool.execute(new MyTask("任务" + i));
        }

        // 3. 用完关闭线程池
        pool.shutdown();
    }
}
运行现象

始终只有3 个线程轮流复用执行 5 个任务,多余任务排队等待。

核心结论

线程不会新建更多,固定并发数,可控稳定。


3.2 newSingleThreadExecutor () 单线程池

特点
  1. 池内永远只有 1 个线程
  2. 所有任务按顺序排队执行,不会并发
  3. 适合:需要任务有序执行、不能同时跑的场景
完整代码

java

运行

复制代码
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class SingleThreadDemo {
    public static void main(String[] args) {
        // 创建单线程池
        ExecutorService pool = Executors.newSingleThreadExecutor();

        // 提交4个任务
        for (int i = 1; i <= 4; i++) {
            pool.execute(new MyTask("有序任务" + i));
        }

        pool.shutdown();
    }
}
运行现象

任务 1 执行完→任务 2→任务 3→任务 4,严格串行有序,无并发争抢。


3.3 newCachedThreadPool () 可缓存线程池

特点
  1. 无固定线程数,按需创建
  2. 来了任务有空闲线程就复用,没有就新建
  3. 空闲线程闲置 60 秒自动回收
  4. 适合:短期大量瞬时任务,不适合高并发长耗时业务(容易无限建线程)
完整代码

java

运行

复制代码
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class CachedThreadPoolDemo {
    public static void main(String[] args) {
        ExecutorService pool = Executors.newCachedThreadPool();

        // 提交6个任务
        for (int i = 1; i <= 6; i++) {
            pool.execute(new MyTask("缓存任务" + i));
        }

        pool.shutdown();
    }
}
运行现象

瞬间创建多个线程,几乎所有任务同时并发执行


下午 2.5h 线程池使用细节 + 综合案例

1 线程池使用标准步骤(必背模板)

  1. 通过 Executors 创建线程池 ExecutorService
  2. 自定义任务类 implements Runnable,重写 run ()
  3. 线程池对象调用 execute(任务对象) 提交任务
  4. 所有任务执行完毕,调用 shutdown() 关闭线程池

2 线程池执行核心特点

  1. 线程复用 :线程执行完任务不销毁,回到池里等待下一个任务
  2. 固定线程池:最大并发 = 设置的线程数,多余任务排队
  3. 单线程池:天然串行,任务排队有序执行
  4. 缓存线程池:弹性扩容,空闲线程自动回收

3 综合案例 1:固定线程池观察线程复用

直接用上面 newFixedThreadPool(3) 代码重点观察:

  • 始终就那 3 个线程名称反复出现
  • 不是每次任务都新建线程 → 完美复用

4 综合案例 2:单线程池有序排队

newSingleThreadExecutor() 代码观察:任务严格按提交顺序执行,无抢占、无乱序。


晚上 1.5h 复盘 + 巩固练习

必做练习

  1. 分别手写三种线程池,提交任务运行,看执行区别
  2. 对比:普通 new Thread() 每次都是新线程;线程池复用旧线程
  3. 练习 shutdown() 关闭,不关闭程序可能一直不退出

今日核心总结表格

表格

线程池类型 线程数量 执行特点 适用场景
FixedThreadPool 固定 n 个 固定并发,任务排队 常规业务、控制并发量
SingleThreadExecutor 固定 1 个 串行有序执行 任务必须按顺序执行
CachedThreadPool 弹性不固定 按需新建、空闲回收 短期大量瞬时小任务

原计划缺失 超重要知识点(必须补充,Day28 必学)

1. 为什么阿里开发规范禁止用 Executors 创建线程池

  • Fixed/Single 任务队列无界,任务太多内存溢出 OOM
  • Cached 无最大线程限制,任务暴增会无限创建线程拖垮服务器
  • 实际开发要用:ThreadPoolExecutor 手动创建底层线程池(后续学)

2. shutdown () 注意事项

  • shutdown()不再接受新任务,已提交任务执行完再关闭
  • 不调用 shutdown:线程池核心线程一直存活,程序不会自动结束

3. 线程池核心底层七大参数(先认知,后续深挖)

核心线程数、最大线程数、空闲存活时间、阻塞队列、拒绝策略等,是线程池本质,Executors 只是封装工具。

4. 任务提交两种方式

  • execute(Runnable):无返回值
  • submit(Callable):有返回值,可以获取线程执行结果(衔接 Day21 Callable)

Day28 验收标准(强化版)

  1. 能口述线程池作用、四大优势,说出和原生 new Thread 的区别
  2. 能手写三种线程池创建代码、提交任务、关闭线程池
  3. 能说出三种线程池各自特点、运行现象、适用场景
  4. 理解线程复用原理,知道线程执行完不销毁
  5. 知道 Executors 弊端,了解实际开发不推荐直接使用
线程池 执行顺序 线程数量 抢占式?
Fixed 固定线程池 乱序 固定 ✅ 抢占式
Cached 可缓存线程池 最乱、完全无序 自动增加 抢占式(最强)
Single 单线程池 绝对有序 1 个 ❌ 不抢占,排队执行
相关推荐
随风丶飘9 小时前
DeepSeek TUI 让后端告别窗口切来切去
java·ai编程
星幻元宇VR9 小时前
VR科普大空间|法治、禁毒、消防一体化沉浸式教育新模式
科技·学习·安全·vr·虚拟现实
中国胖子风清扬9 小时前
PageIndex:用推理替代向量的下一代 RAG 架构
java·spring boot·python·spring·ai·embedding·rag
带刺的坐椅9 小时前
Solon Flow 实战:用 50 行 YAML 实现一个请假审批流(含中断恢复、并行网关、条件分支)
java·solon·工作流·审批流·流程编排
张二娃同学9 小时前
02_C语言数据类型_整型浮点型字符型一次讲清楚
android·java·c语言
程序猿乐锅9 小时前
【Tilas|第九篇】登录认证功能实现
java·笔记·tlias
optimistic_chen9 小时前
【AI Agent 全栈开发】RAG(检索增强生成)
java·linux·运维·人工智能·ai编程·rag
我的xiaodoujiao9 小时前
API 接口自动化测试详细图文教程学习系列19--添加封装其他的方法
开发语言·python·学习·测试工具·pytest
落痕的寒假9 小时前
[深度学习] 大模型学习8上-推理部署框架llama.cpp与Ollama使用指北
深度学习·学习·llama