Java线程池
Java接口
public class ThreadPoolTest {
public static void main(String[] args) {
ExecutorService e1 = Executors.newSingleThreadPool();
ExecutorService e2 = Executors.newCachedThreadPool();
ExecutorService e3 = Executors.newFixedThreadPool();
ExecutorService e4 = Executors.newScheduledThreadPool(10);
}
}
本质上前三个最终都调用了ThreadPoolExecutor,知识传进去的参数不一样
eg
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
参数分别为核心线程数,最大线程数,线程存活时间,时间单位,阻塞队列
基本的流程为,先创建核心线程接受请求,在数量达到最大值后请求进入阻塞队列,阻塞队列如果满了,就创建普通线程执行后续请求,注意是后续请求而不是先执行队列里面的。如果线程总数达到了maximumPoolSize,并且所有线程都在工作中,如果还有新的请求就会抛出异常。
上面大致是最坏情况,一般来说,在队列满之前核心线程或者可能就执行完请求了,那么根据keepAliveTime参数,如果普通线程在这段时间内没有接受到请求,那么这个普通线程就会被GC。注意核心线程不会被回收。
cachedThreadPool
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
核心线程数0,总线程数最大值,同步队列大小为0
所以一开始任务进来后因为核心线程已经达到了最大值0,所以要进入队列,但队列的大小也为0,所以会创建普通线程执行任务,知道线程数达到Integer.MAX_VALUE后还有新任务进入,才会抛异常。没事情干的线程60s后被回收。(60s是否合理?线程数量太大会不会OOM?)
fixedThreadPool
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
核心线程数=最大线程数,没事干的普通线程会立刻销毁,但是因为永远不会有普通线程,所以线程的数量是固定的,没有线程会被销毁,此外队列是无限大的。(无穷队列是否会OOM?)
标签:nThreads,队列,ThreadPool,线程,new,ExecutorService,public From: https://www.cnblogs.com/antidogmatist/p/16964620.html