线程池ThreadPoolExecutor使用

线程池可以通过Executors快捷的创建。

创建可缓存的线程池,线程数可以无限多。

ExecutorService service1 = Executors.newCachedThreadPool();

创建定长的线程池。

ExecutorService service2 = Executors.newFixedThreadPool(10);

创建定长的线程池,可定时周期执行。

ExecutorService service3 = Executors.newScheduledThreadPool(10);

创建单一线程的线程池。

ExecutorService service4 = Executors.newSingleThreadExecutor();


为了便于理解,看下内部创建的方式:

public static ExecutorService newCachedThreadPool() {
	return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue());
}
public static ExecutorService newFixedThreadPool(int paramInt) {
	return new ThreadPoolExecutor(paramInt, paramInt, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue());
}

创建线程池参数:

ThreadPoolExecutor pool = new ThreadPoolExecutor(1, // coreSize,核心线程数
				2, // MaxSize,最大线程数
				60, // 60,线程空闲的时间,超过时间,则会被销毁
				TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(3) // 指定一种队列,存放任务待处理。
																		// (有界队列)
				// new LinkedBlockingQueue<Runnable>()
				, new MyRejected()// 拒绝策略
		);


pool中添加任务数为1,因为核心线程为1,会被立即执行。

pool中添加任务数为2/3/4,因为核心线程为1,会被放到队列中等待执行。

pool中添加任务数为5,因为核心线程为1,队列为3,此时核心线程正在执行,且队列已经满了,但是max为2,所以会启动一个新的线程执行任务5。(此时如果1还没有执行完,那么5会优先2/3/4执行)。

pool中添加任务数为6,因为核心线程为1,队列为3,此时核心线程正在执行,且队列已经满了,且max为2,此时任务6不知道既没线程去执行,又没有队列存储,只能走拒绝策略。

整体的顺序,添加任务时首先看核心线程还有没有,有就立即执行,没有就放到队列中等待,当队列满了,就看max-core线程数还有没有空间,如果有就立即启动线程执行,没有就走拒绝策略。

当队列采用LinkedBlockingQueue这种无界队列时,max就没有用了,因为超过core的任务会放到队列中等待执行。


所以可以看到newCachedThreadPool的创建方式:


core为0,max为Integer最大值,空闲存活时间为60s,队列为没有空间的SynchronousQueue,此时可以知道,这个队列是没用的,任务全部会执行。

再看下newFixedThreadPool的创建方式:


core和max都为我们设置的固定大小的线程数,队列是无界队列,即最大可以同时运行我们设置的任务数。

newScheduledThreadPool的创建方式,可定时执行的原因是因为队列使用的是DelayedWorkQueue(对DelayQueue的优化



newSingleThreadExecutor的创建方式,单一线程:


猜你喜欢

转载自blog.csdn.net/ch_show/article/details/79461204