🧠一、为什么需要多线程?在单线程程序中,一个任务执行时,其他任务必须等待。多线程的优势在于:
资源利用率更高:IO密集型任务可以异步处理
提升响应速度:前端不卡顿,用户体验好
任务可并发执行:大大提高吞吐量
常见应用场景包括:
Web服务器处理并发请求
定时任务并发调度
后台批量任务处理
🧩二、Java 中的线程创建方式Java提供了三种创建线程的方式:
1. 继承 Thread 类代码语言:javascript复制class MyThread extends Thread {
@Override
public void run() {
System.out.println("Thread运行中:" + Thread.currentThread().getName());
}
}使用:
代码语言:javascript复制new MyThread().start();2. 实现 Runnable 接口(推荐)
代码语言:javascript复制class MyRunnable implements Runnable {
public void run() {
System.out.println("Runnable运行中:" + Thread.currentThread().getName());
}
}使用:
代码语言:javascript复制Thread t = new Thread(new MyRunnable());
t.start();3. 实现 Callable 接口 + FutureTask适合有返回值的任务:
代码语言:javascript复制Callable
Thread.sleep(1000);
return "任务完成";
};
FutureTask
new Thread(future).start();
System.out.println(future.get());🧰三、为什么要使用线程池?线程池(ThreadPool)能避免频繁创建和销毁线程带来的性能浪费,适合高并发场景。
优点:
降低资源开销
提升响应速度
易于管理线程数量
支持任务排队、超时、拒绝策略等高级特性
🔍四、线程池核心参数详解(ThreadPoolExecutor)代码语言:javascript复制new ThreadPoolExecutor(
corePoolSize, // 核心线程数
maximumPoolSize, // 最大线程数
keepAliveTime, // 非核心线程的存活时间
unit, // 时间单位
workQueue, // 任务队列
threadFactory, // 线程工厂
handler // 拒绝策略
);常见队列类型: ArrayBlockingQueue:有界阻塞队列(推荐)
LinkedBlockingQueue:无界队列,可能OOM
SynchronousQueue:任务直接交给线程,不存储
拒绝策略(RejectedExecutionHandler): AbortPolicy(默认):抛出异常
CallerRunsPolicy:由调用者线程处理任务
DiscardPolicy:直接丢弃任务
DiscardOldestPolicy:丢弃最老的任务,尝试重新提交
🧪五、实战:使用线程池批量处理任务👇 需求:我们有一个任务列表,每个任务模拟耗时1秒。希望并发执行,提升效率。
✅ 代码实战:代码语言:javascript复制import java.util.concurrent.*;
public class ThreadPoolExample {
public static void main(String[] args) throws InterruptedException {
ExecutorService executor = new ThreadPoolExecutor(
4, 8, 60, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(10),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.CallerRunsPolicy());
for (int i = 1; i <= 20; i++) {
final int taskId = i;
executor.execute(() -> {
System.out.println("执行任务 " + taskId + ",线程:" + Thread.currentThread().getName());
try {
Thread.sleep(1000); // 模拟耗时任务
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
executor.shutdown();
executor.awaitTermination(1, TimeUnit.MINUTES);
System.out.println("全部任务执行完毕!");
}
}🧾输出示例:代码语言:javascript复制执行任务 1,线程:pool-1-thread-1
执行任务 2,线程:pool-1-thread-2
...
执行任务 20,线程:pool-1-thread-4
全部任务执行完毕!🎯六、如何选择线程池类型?场景
推荐线程池
短时间大量小任务
FixedThreadPool
任务不多但耗时
CachedThreadPool
定时/周期任务
ScheduledThreadPool
高并发+强控制
自定义 ThreadPoolExecutor
🧯七、线程池的最佳实践 尽量设置线程池为有界队列,避免OOM
合理设置corePoolSize和maxPoolSize,可参考CPU核心数
定期监控线程池状态(活跃线程数、队列长度等)
关闭线程池:shutdown() 或 shutdownNow()
❤️八、写在最后:点赞收藏支持一下!线程池是Java后端工程师的必修课,学会它不仅能写出高性能代码,也能在面试中脱颖而出!
如果你觉得这篇文章对你有帮助,不妨:
👉 点个赞鼓励一下我
👉 点个收藏防止下次找不到
👉 有问题欢迎评论区交流讨论!
我们下篇文章见!