本文介绍了Java中三种常用的线程池:FixedThreadPool、CachedThreadPool和ScheduledThreadPool,分别介绍了它们的原理、代码示例以及使用注意事项。FixedThreadPool适用于并发量固定的场景,CachedThreadPool适用于执行时间短的任务,ScheduledThreadPool适用于定时任务和周期性任务。在使用线程池时需要注意线程池的使用场景和线程池中线程的数量,同时在关闭线程池时需要等待已提交任务执行完成后再关闭。
线程池有三种:FixedThreadPool、CachedThreadPool和ScheduledThreadPool。
一、FixedThreadPool
1 原理:
创建一个固定大小的线程池,线程池中的线程数始终固定不变。当有新的任务提交时,如果线程池中有空闲的线程,则立即执行;如果没有,则把任务放入任务队列等待执行。
2 代码示例:
ExecutorService executor = Executors.newFixedThreadPool(5);
for (int i = 0; i < 10; i++) {
executor.execute(new MyRunnable());
}
executor.shutdown();
3 注意事项:
- 固定大小的线程池适用于任务数量已知且相对固定的情况。
- 如果所有线程都在执行任务,新的任务会被暂时放入任务队列等待执行,如果任务队列已满则会抛出任务拒绝异常RejectedExecutionException。
- 执行shutdown()方法后,线程池不会再接受新的任务,但已提交的任务会继续执行,直到所有任务执行完毕。
二、CachedThreadPool
1 原理:
创建一个可缓存的线程池,线程池中的线程数可以根据需要进行自动扩展或缩减。当有新的任务提交时,如果有空闲的线程则会立即执行,如果没有则会创建新的线程执行任务。
代码示例:
ExecutorService executor = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
executor.execute(new MyRunnable());
}
executor.shutdown();
2 注意事项:
- 可缓存的线程池适用于执行时间较短的任务。
- 如果在执行任务时有空闲线程,则会利用空闲线程执行任务,否则会创建新的线程执行任务。
- 当线程池中的线程数超过任务的数目时,空闲的线程会自动销毁。
三、ScheduledThreadPool
1 原理:
创建一个定长线程池,支持定时及周期性任务执行。当有新的任务提交时,线程池会安排线程执行任务,如果当前线程正在执行任务,则会等待任务执行完成后再执行下一个任务。
2 代码示例:
ScheduledExecutorService executor = Executors.newScheduledThreadPool(5);
executor.schedule(new MyRunnable(), 5, TimeUnit.SECONDS);
executor.shutdown();
3 注意事项:
- 定时任务和周期性任务的执行时间不一定精确,会受到线程池中线程的数量和运行状态的影响。
- 如果定时任务和周期性任务的执行时间过长或抛出异常,则会影响后续任务的执行。
- 执行shutdown()方法后,线程池会等待已提交任务执行完成后再关闭,如果需要立即关闭线程池可以使用shutdownNow()方法。
四、总结:
线程池有三种:FixedThreadPool、CachedThreadPool和ScheduledThreadPool。FixedThreadPool适用于并发量固定的场景,CachedThreadPool适用于执行时间短的任务,ScheduledThreadPool适用于定时任务和周期性任务。在使用线程池时需要注意线程池的使用场景和线程池中线程的数量,避免线程池满载时出现任务拒绝的异常。同时,在关闭线程池时需要等待已提交任务执行完成后再关闭。