一、线程池:
Executors是创建线程池的工厂方法,首先看Executors的所有方法:其中有三个比较常用:
以上三个方法返回的对象不同,其实看看源码就清楚了:
public interface ScheduledExecutorService extends ExecutorService {
ScheduledFuture<?> schedule(Runnable arg0, long arg1, TimeUnit arg3);
<V> ScheduledFuture<V> schedule(Callable<V> arg0, long arg1, TimeUnit arg3);
ScheduledFuture<?> scheduleAtFixedRate(Runnable arg0, long arg1, long arg3, TimeUnit arg5);
ScheduledFuture<?> scheduleWithFixedDelay(Runnable arg0, long arg1, long arg3, TimeUnit arg5);
}
一、线程池执行如下:有新任务——>在corePoolSize范围内新增线程处理任务——>corePoolSize满,则放入任务队列——>队列满,则在maximumPoolSize范围内新增线程处理任务——>队列满,报错抛异常
二、newFixedThreadPool(int arg)和newSingleThreadScheduledExecutor()线程池结构:
1)先看下newFixedThreadPool(int arg)固定线程数的线程池源码,证明corePoolSize和maximumPoolSize相等,因为任务队列是无界的,所以一般不会用到最大线程参数,跟corePoolSize数量一样即可。
public static ExecutorService newFixedThreadPool(int arg) {
return new ThreadPoolExecutor(arg, arg, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue());
}
其中ThreadPoolExecutor构造方法为:
public ThreadPoolExecutor(int arg0, int arg1, long arg2, TimeUnit arg4, BlockingQueue<Runnable> arg5, ThreadFactory arg6, RejectedExecutionHandler arg7) {
this.ctl = new AtomicInteger(ctlOf(-536870912, 0));
this.mainLock = new ReentrantLock();
this.workers = new HashSet();
this.termination = this.mainLock.newCondition();
if(arg0 >= 0 && arg1 > 0 && arg1 >= arg0 && arg2 >= 0L) {
if(arg5 != null && arg6 != null && arg7 != null) {
this.corePoolSize = arg0;
this.maximumPoolSize = arg1;
this.workQueue = arg5;
this.keepAliveTime = arg4.toNanos(arg2);
this.threadFactory = arg6;
this.handler = arg7;
} else {
throw new NullPointerException();
}
} else {
throw new IllegalArgumentException();
}
}
2)newSingleThreadScheduledExecutor()可简单的理解只有一个线程的调度线程池。可以看到其实还是使用的ThreadPoolExecutor类对象,虽然有点区别,但大致可以理解为newFixedThreadPool(int arg)。
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
三、newScheduledThreadPool(int arg)线程池结构:
先看源码:其中队列使用的是DelayedWorkQueue(详见线程池总结2),定时调度任务由此队列实现:该queue同时具有PriorityQueue(优先级大的元素会放到队首)和DelayQueue(队列里第一个元素的getDelay返回值大于0时,则take调用会阻塞)的功能
public ScheduledThreadPoolExecutor(int arg0) {
super(arg0, Integer.MAX_VALUE, 0L, TimeUnit.NANOSECONDS, new ScheduledThreadPoolExecutor.DelayedWorkQueue());
}
四、拓展:
像newCachedThreadPool()这种,用SynchronousQueue这种队列,即消费者生产者模式,队列里同时最多存在一个任务,被取走后新开一个线程任务处理(线程最大数为Integer最大值),才能再添加进来新的。
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue());
}
五、对比:
1、newFixedThreadPool 和 newSingleThreadExecutor: 请求处理队列可能会耗费无限大的内存。
2、newCachedThreadPool 和 newScheduledThreadPool: 因为线程最大数是 Integer.MAX_VALUE,也会耗费无限大内存。