一、JDK自带的四种线程池
1、newCachedThreadPool 创建一个可缓存线程池,如果线程池长度超过了处理当前任务的需要,可灵活的回收空闲的线程。
2、newFixedThreadPool 创建一个定长线程池,可控线程最大并发数,超出的线程会在队列中等待
3、newScheduledThreadPool创建一个定长线程池,支持周期性任务执行。
4、newSingleThreadPool 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务。
public static void main(String[] args) throws ExecutionException, InterruptedException {
//可缓存的线程池
ExecutorService pool = Executors.newCachedThreadPool();
//定长线程池
ExecutorService pool1 = Executors.newFixedThreadPool(5);
//定长线程池,支持定时及周期性任务
ScheduledExecutorService pool2 = Executors.newScheduledThreadPool(5);
//单线程化的线程池
ExecutorService pool3 = Executors.newSingleThreadExecutor();
for (int i = 0; i < 5; i++) {
pool1.submit(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("hello pool");
});
}
}
二、自定义线程池(推荐使用)
通过查看上面线程的源码,我们可以试着模仿进行自定义线程池。
可以看到 newFixedThreadPool 实现线程池是通过ThreadPoolExecutor对象,传入需要的参数进行创建。
下面介绍一下线程池中参数的意义:
corePoolSize | 核心线程数,线程池里的线程数量,核心线程池大小 |
maximumPoolSize | 最大线程数,线程池里的最大线程数量 |
keepAliveTime | 当线程池线程数量大于corePoolSize时候,多出来的空闲线程,多长时间会被销毁 |
unit | 时间单位,TimeUnit |
workQueue | 任务队列,用于存放提交但是尚未被执行的任务 |
threadFactory | 线程工厂,用于创建线程,线程工厂就是给我们new线程的 |
handler | 所谓拒绝策略,是指将任务添加到线程池中时,线程池拒绝该任务所采取的相应策略 |
ExecutorService executor = new ThreadPoolExecutor(5, 8, 5, TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>());
拒绝策略呢?我没弄上去,因为它有默认的,那么下面介绍一下它自带的四种拒绝策略,当然拒绝策略也可以自己定义,参考它自带的拒绝策略写就行了。
- AbortPolicy:直接抛出异常,默认策略;
- CallerRunsPolicy:用调用者所在的线程来执行任务;
- DiscardOldestPolicy:丢弃阻塞队列中最靠前的任务,并执行当前任务;
- DiscardPolicy:直接丢弃任务;
我们看源码,它自带的拒绝策略是AbortPolicy
当然它还自带了默认的线程工厂,线程工厂就是创建线程的,也可以自定定义,还是参考源码。
三、总结
那么java中线程池的创建和使用就介绍到这了。如果以后有机会的话,我会深入源码研究,再写一些详细的介绍。