创建可缓存的线程池(CachedThreadPool)
适合执行大量的短期异步任务。
//形参下同
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, //核心线程数
Integer.MAX_VALUE,//最大线程数
60L, //最大存活时间
TimeUnit.SECONDS,//时间单位
new SynchronousQueue<Runnable>()//阻塞队列
);
}
核心线程数设置为0,最大线程数设置为Integer的最大值。即当有任务进来时,先查看有没有可重用线程,如果没有可用线程就直接创建新线程。这就是最大线程数设为Integer.MAX_VALUE的原因,能保证任务进来一定有线程分配给它。阻塞队列使用了SynchoronousQueue,这是个不存储元素的阻塞队列。
创建单线程的线程池(SingleThreadExecutor)
适合需要顺序执行任务的场景
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
public LinkedBlockingQueue() {
this(Integer.MAX_VALUE);
}
最大线程数和核心线程数都设置为1,即当前线程池内只会有一个线程来执行任务,其余任务都会进入LinkedBlockingQueue中进行阻塞排队。其中LinkedBlockingQueue是一个以由链表结构组成的有界队列,但我们通过源码可以看到它的大小设置为了Integer的最大值,这个界限非常的大,可以当做无界队列来使用。
创建固定大小的线程池(FixedThreadPool)
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
核心线程数和最大线程数相同,即确保了线程池中只能存在nThreads个线程。
创建具有定时任务执行功能的线程池(ScheduledThreadPool)
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue());
}
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ScheduledThreadPoolExample {
public static void main(String[] args) {
int nThreads = 3; // 线程池中线程数目
// 创建一个定时任务执行功能的线程池
ScheduledExecutorService executor = Executors.newScheduledThreadPool(nThreads);
// 定时执行任务
Runnable task = () -> {
System.out.println("执行任务 - " + Thread.currentThread().getName());
// 任务逻辑
};
// 延迟1秒后执行任务
executor.schedule(task, 1, TimeUnit.SECONDS);
// 在初始延迟0秒后,每隔2秒执行任务
executor.scheduleAtFixedRate(task, 0, 2, TimeUnit.SECONDS);
// 等待一段时间后关闭线程池
try {
Thread.sleep(10000); // 主线程休眠10秒钟
} catch (InterruptedException e) {
e.printStackTrace();
}
executor.shutdown(); // 关闭线程池
}
}
底层使用了无界延迟队列
顺带一提,使用自定义线程池的方式创建线程可以根据业务需求配备相应的线程数量、等待队列和拒绝策略等参数,效果会更佳