Appearance
15_线程池
线程池是什么?
线程池是一种多线程处理形式。在任务执行过程中,将任务提交到线程池中,线程池中的线程会不断从队列中获取任务并进行执行。当一个任务完成后,该线程不会被销毁,而是返回到线程池中等待下一个任务的分配。
为什么要使用线程池?
- 降低资源消耗:通过重复利用已创建的线程,避免频繁地创建和销毁线程所带来的系统开销。
- 提高系统性能:合理控制同时执行的任务数量,防止过多线程导致的资源竞争和上下文切换问题。
- 简化线程管理:统一管理和分配线程,减少手动管理多条独立线程的工作量。
线程池的创建方式及区别
Java 提供了 Executor
框架来实现任务执行服务。通过不同的工厂方法可以创建不同类型的线程池:
1. Fixed-size pool(固定大小线程池)
- 使用
Executors.newFixedThreadPool(int nThreads)
创建。 - 特点:
- 线程数量固定,不会根据负载变化而调整。
- 如果所有线程都在忙,则新任务会被排队等待执行。
- 适用场景:适合处理任务数量有限、希望控制资源使用的情况。
2. Single thread pool(单个线程池)
- 使用
Executors.newSingleThreadExecutor()
创建。 - 特点:
- 只有一个工作线程,所有提交的任务都会排队等待执行。
- 如果这个唯一的线程被阻塞,则后续任务会按顺序等待直到该线程空闲。
- 适用场景:适合需要顺序执行的任务。
3. Cached thread pool(可扩展线程池)
- 使用
Executors.newCachedThreadPool()
创建。 - 特点:
- 线程数量动态调整,根据任务负载自动增加或移除线程。
- 如果一个线程空闲了一段时间(默认是60秒),则会被回收和终止。
- 适用场景:适合高并发、短时间的任务执行。
4. Scheduled thread pool(定时任务池)
- 使用
Executors.newScheduledThreadPool(int corePoolSize)
创建。 - 特点:
- 支持定期或延迟任务的执行,类似于一个调度服务。
- 适用场景:适合需要周期性检查或清理操作的任务。
示例代码
java
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolExample {
public static void main(String[] args) {
// 创建固定大小的线程池(Fixed-size pool)
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5);
// 提交任务到线程池
for (int i = 0; i < 10; i++) {
final int taskNumber = i;
fixedThreadPool.execute(() -> {
System.out.println("Task " + taskNumber + ": 正在执行");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Task " + taskNumber + ": 执行完毕");
});
}
// 关闭线程池
fixedThreadPool.shutdown();
// 创建单个线程池(Single thread pool)
ExecutorService singleThreadPool = Executors.newSingleThreadExecutor();
for (int i = 0; i < 3; i++) {
final int taskNumber = i;
singleThreadPool.execute(() -> {
System.out.println("Task " + taskNumber + ": 正在执行");
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Task " + taskNumber + ": 执行完毕");
});
}
// 关闭线程池
singleThreadPool.shutdown();
// 创建可扩展的线程池(Cached pool)
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
for (int i = 0; i < 15; i++) {
final int taskNumber = i;
cachedThreadPool.execute(() -> {
System.out.println("Task " + taskNumber + ": 正在执行");
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Task " + taskNumber + ": 执行完毕");
});
}
// 关闭线程池
cachedThreadPool.shutdown();
// 创建定时任务池(Scheduled pool)
ExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(2);
Runnable runnable = () -> {
System.out.println("定期任务:执行中...");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("定期任务:完成");
};
// 每隔2秒执行一次
scheduledThreadPool.scheduleAtFixedRate(runnable, 2, 2, java.util.concurrent.TimeUnit.SECONDS);
try {
Thread.sleep(10_000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 关闭线程池
scheduledThreadPool.shutdown();
}
}
总结
- Fixed-size pool:适合任务数量有限、需要控制资源使用的情况。
- Single thread pool:适合顺序执行的任务,确保所有任务按顺序处理。
- Cached pool:适合高并发、短时间的任务,能够快速响应新请求。
- Scheduled pool:适合需要定期或延迟执行的任务。
选择合适的线程池类型取决于具体的业务场景和需求。