多线程入门到进阶:线程模型、状态、任务提交与线程池基础
大约 3 分钟
多线程入门到进阶:线程模型、状态、任务提交与线程池基础
新手一屏速览
- 任务优于线程:使用 Executor 提交任务;线程池管理并发资源
- 中断是协作机制而非强制停止;编写可中断的阻塞与轮询
- 合理配置核心线程数、队列与拒绝策略;避免无限队列吞没内存
1. 线程与任务模型
- 线程代表执行上下文;任务(Runnable/Callable)代表工作单元
- 使用
Executors.newFixedThreadPool/ThreadPoolExecutor提交任务而非手工管理线程
2. 线程状态与中断
- NEW/RUNNABLE/BLOCKED/WAITING/TIMED_WAITING/TERMINATED
- 中断通过
Thread.interrupt()标记;阻塞方法抛InterruptedException,需恢复中断或退出
try { Thread.sleep(1000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); }3. 守护线程与生命周期
- 守护线程不阻止 JVM 退出;后台任务/监控用守护线程,业务核心用非守护
- 使用
ExecutorService.shutdown()与awaitTermination()优雅停止
4. 线程池基础
最近建一些几十个工作内推群,各大城市都有,群里目前已经收集了很多内推岗位,大厂、中厂、小厂、外包都有。 欢迎HR、开发、测试、运维和产品加入。

扫描下方微信,备注:网站+所在城市,即可拉你进工作内推群。

- 核心参数:corePoolSize、maximumPoolSize、keepAliveTime、workQueue、threadFactory、handler
- 拒绝策略:CallerRuns/Abort/Discard/DiscardOldest;在边界层处理与告警
5. 可观测性与调试
- 命名线程便于诊断;暴露指标(队列长度、任务耗时、拒绝次数)
- 使用 jstack/JFR 分析阻塞与热点;对长时间运行任务做切分与超时
6. 练习
- 为计算密集/IO 密集任务分别配置线程池,压测与观测指标
- 实现一个可中断的轮询器,正确处理中断与关闭
示例代码(可直接复制运行)
示例一:可中断的工作循环
public class InterruptibleWorker implements Runnable {
public void run() {
while (!Thread.currentThread().isInterrupted()) {
// 模拟工作
try { Thread.sleep(100); }
catch (InterruptedException e) {
Thread.currentThread().interrupt(); // 恢复中断并退出
}
}
System.out.println("stopped");
}
public static void main(String[] args) throws Exception {
Thread t = new Thread(new InterruptibleWorker(), "worker");
t.start();
Thread.sleep(300);
t.interrupt();
t.join();
}
}示例二:线程池提交任务与优雅关闭
import java.util.concurrent.*;
public class PoolSubmit {
public static void main(String[] args) throws Exception {
ExecutorService es = Executors.newFixedThreadPool(4, r -> {
Thread t = new Thread(r);
t.setName("biz-" + t.getId());
return t;
});
Future<Integer> f = es.submit(() -> 1 + 1);
System.out.println(f.get());
es.shutdown();
es.awaitTermination(5, TimeUnit.SECONDS);
}
}示例三:守护线程
public class DaemonDemo {
public static void main(String[] args) throws Exception {
Thread t = new Thread(() -> {
while (true) { /* 后台监控 */ }
}, "daemon");
t.setDaemon(true);
t.start();
Thread.sleep(200); // 主线程结束后 JVM 可退出
}
}示例四:拒绝策略与有界队列
import java.util.concurrent.*;
public class RejectionPolicyDemo {
public static void main(String[] args) {
BlockingQueue<Runnable> q = new ArrayBlockingQueue<>(2);
ThreadPoolExecutor ex = new ThreadPoolExecutor(
1, 1, 0L, TimeUnit.MILLISECONDS, q,
new ThreadPoolExecutor.CallerRunsPolicy()); // 拒绝时在调用线程执行
for (int i=0;i<5;i++) {
final int id = i;
ex.execute(() -> {
try { Thread.sleep(200); } catch (InterruptedException ignored) {}
System.out.println("task " + id + " by " + Thread.currentThread().getName());
});
}
ex.shutdown();
}
}