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 个 ❌ 不抢占,排队执行
相关推荐
骄马之死5 小时前
SpringMVC + SpringBoot 核心知识点总结
java·spring boot·后端
xqqxqxxq6 小时前
哈希表(HashMap)技术学习笔记
笔记·学习·散列表
生而为虫6 小时前
[学习记录] 幼儿学习拼音html游戏
学习·游戏
AOwhisky6 小时前
MySQL 学习笔记(第四期):SQL 语言之多表查询
linux·运维·网络·数据库·笔记·学习·mysql
世辰辰辰6 小时前
批量修改图片/文本名子
开发语言·python·批量修改文件名
郑洁文7 小时前
基于Spring Boot的流浪动物救助网站
java·spring boot·后端·毕设·流浪动物救助
xian_wwq7 小时前
【学习笔记】「大模型安全:攻击面演化史」第 07 篇-安全左移
人工智能·笔记·学习
秋雨梧桐叶落莳7 小时前
iOS——NSUserDefaults学习
学习·macos·ios·objective-c·cocoa
螺丝钉code7 小时前
JAVA项目 Claude code CLAUDE.md 到底应该怎么写
java·人工智能·claude code
易小染8 小时前
AI-Agent学习-LangChain-01
学习·langchain