Java的线程池Executors

一、前言

有时候我们需要创建大量的线程来执行一些主线程以外的任务,然而频繁的建立Thread会可能占用过多系统资源导致死机或oom。如果能建立一个Thread Pool来管理这些Thread并加以复用,对于我们的系统性能会有很大的改善。

二、创建线程池

ExecutorService是JDK提供的框架,可简化异步模式下任务的执行。一般而言, ExecutorService自动提供线程池和API来为其分配任务。

创建ExecutorService的最简单方法是使用Executors类的工厂方法之一。例如,以下代码行将创建一个包含10个线程的线程池:

ExecutorService executor = Executors.newFixedThreadPool(10);

另外Executors还提供了其他的建立线程池方式:

1、newCachedThreadPool:创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
2、newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
3、newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
4、newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。

三、线程池示例

我们通过一个示例进一步了解线程池,我们通过newFixedThreadPool方法建立Thread pool,线程池固定大小为5,我们通过for循环产生10个Runnable,由于Thread pool中只有个可用的Thread,所以后来建立的5个Runnable必须等待Thread空闲后才能被执行:

public static void main(String[] args) {
	ExecutorService excutorService = Executors.newFixedThreadPool(5);
	for (int i = 0; i < 10; i++) {
		final int count = i;
		excutorService.submit(new Runnable() {
			public void run() {
				System.out.println(count);
				try {
					Thread.sleep(2000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		});
	}
	excutorService.shutdown();
}

Submit()向 ExecutorService提交 Callable或 Runnable任务,并返回 Future类型的结果。需要注意的是没有要处理的任务时,不会自动销毁ExecutorService。它会继续存在,并等待新的工作完成。因为等待中的ExecutorService将导致JVM继续运行,所有我们最好关闭ExecutorService。

excutorService.shutdown();

四、判断线程池是否执行完成

有时候我们需要判断线程池中所有线程是否执行完成,然后执行后续操作。这个时候我们需要用到isTerminated方法。

while (true) {
	if (excutorService.isTerminated()) {
		System.out.println("所有子线程执行完成。");
		break;
	}
	Thread.sleep(1000);
}

需要注意的是除非首先调用 shutdown 或shutdownNow,否则 isTerminated 永不为 true。

你可能感兴趣的:(Java)