Executors提供的四种线程池

目录

1、newCachedThreadPool

创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。

使用方法:

ExecutorService cachedThreadPool = Executors.newCachedThreadPool();

底层实现:

public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0,Integer.MAX_VALUE,60L, TimeUnit.SECONDS,new SynchronousQueue<Runnable>());
}

通过看其实现可以发现,他实际上是创建一个核心池为0,最大线程为MAX_VALUE的线程池,该线程池使用SynchronousQueue队列。每次添加任务若没有空闲的线程都会创建新的线程去执行。

使用demo:

@Test
public void test_newCachedThreadPool() throws InterruptedException{
	ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
	for (int i = 0; i < 10; i++) {
		final int index = i;
		cachedThreadPool.execute(new Runnable() {
			public void run() {
				try {
					Thread.sleep(index * 1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println(Thread.currentThread().getName());
			}
		});
	}
	Thread.sleep(100000L);
}

运行结果:

可以看到只有一次复用了线程。其他时候都是新创建一个线程执行。
Executors提供的四种线程池


2、newFixedThreadPool

创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。

使用方法:

ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);

底层实现:

public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>());
}

通过看其实现可以发现,他实际上是创建一个核心池、最大线程都为nThreads的固定线程数量的线程池,keepAliveTime为0,标识线程永久存活。该线程池使用LinkedBlockingQueue基于链表的队列,最大长度为Integer.MAX_VALUE。

使用demo:

@Test
public void test_newFixedThreadPool() throws InterruptedException{
	ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
	for (int i = 0; i < 10; i++) {
		final int index = i;
		fixedThreadPool.execute(new Runnable() {
			public void run() {
				try {
					Thread.sleep(index * 1000);
				} catch (InterruptedException e) {
				}
				System.out.println(index + " : "+Thread.currentThread().getName());
			}
		});
	}
	Thread.sleep(100000L);
}

运行结果:

从运行结果可以看到,最多只创建了3个线程。去进行任务处理。
Executors提供的四种线程池


3、newScheduledThreadPool

创建一个定长线程池,支持定时及周期性任务执行。

对于newScheduledThreadPool 的使用和讲解



4、newSingleThreadExecutor

创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。

newFixedThreadPool(1)和newSingleThreadExecutor的区别

Unlike the otherwise equivalent {@code newFixedThreadPool(1)} the returned executor is guaranteed not to be reconfigurable to use additional threads.

newFixedThreadPool(1)在功能上可以实现newSingleThreadExecutor,但是其区别是使用newSingleThreadExecutor,返回的对象是禁止修改的。比如说,通过返回的对象重新设置核心线程池大小。

例如下面的例子,将newFixedThreadPool的核心池由2改为5,同样的做法,使用newSingleThreadExecutor则会报错。:
Executors提供的四种线程池

使用方法:

ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();

底层实现:

public static ExecutorService newSingleThreadExecutor() {
	return new FinalizableDelegatedExecutorService
		(new ThreadPoolExecutor(1, 1,
								0L, TimeUnit.MILLISECONDS,
								new LinkedBlockingQueue<Runnable>()));
}

通过看其实现可以发现,他实际上是先创建一个核心池、最大线程都为1的固定线程数量的线程池,keepAliveTime为0,标识线程永久存活。该线程池使用LinkedBlockingQueue基于链表的队列,最大长度为Integer.MAX_VALUE。然后对这个线程池对象进行封装。

使用demo:

@Test
public void test_newSingleThreadExecutor() throws InterruptedException{
	ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
	for (int i = 0; i < 10; i++) {
		final int index = i;
		singleThreadExecutor.execute(new Runnable() {
			public void run() {
				try {
					System.out.println("按先进先出的顺序执行:"+index);
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		});
	}
	Thread.sleep(100000L);
}

运行结果:

可以看到,是按照任务的添加顺序执行的Executors提供的四种线程池


上一篇:Thread类线程类 ExecutorService 线程池


下一篇:SpringBoot - 使用ExecutorService线程池执行异步任务教程(Runnable任务为例)