Java多线程之ExecutorService使用说明
一、简介
ExecutorService是Java中对线程池定义的一个接口,它java.util.concurrent包中,在这个接口中定义了和后台任务执行相关的方法。
二、线程池
Java给我们提供了一个Executors工厂类
,它可以帮助我们很方便的创建各种类型ExecutorService线程池,Executors一共可以创建下面这四类线程池:
- newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
- newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
- newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
- newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
三、代码举例
import org.junit.Test; import java.util.concurrent.*; /** * @author :gongxr * @description:ExecutorService是Java中对线程池定义的一个接口,它java.util.concurrent包中,在这个接口中定义了和后台任务执行相关的方法。 Java通过Executors提供四种创建线程池的工厂类,分别为: * newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。 * newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。 * newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。 * newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。 */ public class TestExecutorService { /** * newCachedThreadPool:创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。 */ @Test public void test1() throws InterruptedException { ExecutorService cachedThreadPool = Executors.newCachedThreadPool(); Runnable runnable = new Runnable() { @Override public void run() { try { System.out.println(Thread.currentThread().getName() + " 开始工作!"); Thread.sleep((long) (Math.random() * 3000)); System.out.println(Thread.currentThread().getName() + " 工作结束!"); } catch (InterruptedException e) { e.printStackTrace(); } } }; for (int i = 0; i < 5; i++) { cachedThreadPool.execute(runnable); } Thread.sleep(3000); System.out.println("主线程结束!"); cachedThreadPool.shutdown(); } /** * newFixedThreadPool:创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。 */ @Test public void test2() throws InterruptedException { ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3); Runnable runnable = new Runnable() { @Override public void run() { try { System.out.println(Thread.currentThread().getName() + " 开始工作!"); Thread.sleep((long) (Math.random() * 3000)); System.out.println(Thread.currentThread().getName() + " 工作结束!"); } catch (InterruptedException e) { e.printStackTrace(); } } }; for (int i = 0; i < 6; i++) { final int index = i; fixedThreadPool.execute(runnable); } Thread.sleep(6000); fixedThreadPool.shutdown(); System.out.println("主线程结束!"); } /** * newScheduledThreadPool:创建一个定长线程池,支持定时及周期性任务执行。 * 该例中延迟3秒执行。 */ @Test public void test3_1() throws InterruptedException { ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(3); Runnable runnable = new Runnable() { @Override public void run() { System.out.println("delay 3 seconds"); } }; scheduledThreadPool.schedule(runnable, 3, TimeUnit.SECONDS); Thread.sleep(10000); scheduledThreadPool.shutdown(); } /** * newScheduledThreadPool:创建一个定长线程池,支持定时及周期性任务执行。 * 延迟1秒后每3秒执行一次。 */ @Test public void test3_2() throws InterruptedException { ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(3); Runnable runnable = new Runnable() { @Override public void run() { System.out.println("delay 1 seconds, and excute every 3 seconds"); } }; scheduledThreadPool.scheduleAtFixedRate(runnable, 1, 3, TimeUnit.SECONDS); Thread.sleep(10000); scheduledThreadPool.shutdown(); } /** * newSingleThreadExecutor:创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。 */ @Test public void test4() throws InterruptedException { ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor(); for (int i = 0; i < 5; i++) { final int index = i; singleThreadExecutor.execute(new Runnable() { @Override public void run() { try { System.out.println(index); Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } }); } Thread.sleep(10000); singleThreadExecutor.shutdown(); } /** * submit(Callable) * submit(Callable)和submit(Runnable)类似,也会返回一个Future对象, * 但是除此之外,submit(Callable)接收的是一个Callable的实现, * Callable接口中的call()方法有一个返回值,可以返回任务的执行结果, * 而Runnable接口中的run()方法是void的,没有返回值。 */ @Test public void testCallable() throws Exception { ExecutorService executorService = Executors.newCachedThreadPool(); Callable callable = new Callable() { @Override public Object call() throws InterruptedException { String name = Thread.currentThread().getName(); System.out.println("Thread Name:" + name + " 开始工作!"); Thread.sleep((long) (Math.random() * 3000)); System.out.println("Thread Name:" + name + " 结束工作!"); return name; } }; Future future = executorService.submit(callable); System.out.println("主线程继续执行!"); Thread.sleep(3000); // future.get()使得主线程阻塞,等待子线程执行结束 System.out.println("子线程执行完回调结果:" + future.get().toString()); System.out.println("主线程结束!"); executorService.shutdown(); } /** * ExecutorService的shutdown、shutdownNow、awaitTermination用法: * 调用shutdown方法之后,ExecutorService不再接收新的任务,直到当前所有线程执行完成才会关闭,所有之前提交的任务都会被执行。 * 调用shutdownNow方法后,将试图阻止所有正在执行的任务和被提交还没有执行的任务。 * awaitTermination方法的作用:监视各任务的状态是否已经结束,经过指定的时间后,全部完成返回true,反之返回false。 */ @Test public void testShutDown() throws Exception { ExecutorService executorService = Executors.newCachedThreadPool(); Runnable runnable = new Runnable() { @Override public void run() { try { System.out.println(Thread.currentThread().getName() + " 开始工作!"); Thread.sleep(2000); System.out.println(Thread.currentThread().getName() + " 工作结束!"); } catch (InterruptedException e) { System.out.println(Thread.currentThread().getName() + " 子线程中断!"); e.printStackTrace(); } } }; // 线程1 executorService.execute(runnable); Thread.sleep(1000); // 线程2 executorService.execute(runnable); executorService.shutdown(); // 等待一秒后检查子线程运行状态,全部完成返回true if (!executorService.awaitTermination(1, TimeUnit.SECONDS)) { System.out.println("主线程强制中断子线程!"); executorService.shutdownNow(); } Thread.sleep(4000); System.out.println("主线程结束!"); } }
与多线程同步工具结合使用:
/** * ExecutorService实战用法: * 与CountDownLatch线程同步工具结合使用 */ @Test public void testExe() throws Exception { int count = 5; // 任务数量 ExecutorService executorService = Executors.newCachedThreadPool(); CountDownLatch countDownLatch = new CountDownLatch(count); //线程同步工具 for (int i = 1; i <= count; i++) { int taskId = i; executorService.execute(() -> task(taskId, countDownLatch)); } executorService.shutdown(); // 不再接受新任务 countDownLatch.await(); // 等待所有任务完成 // 等待一秒后检查子线程运行状态,全部完成返回true if (!executorService.awaitTermination(1, TimeUnit.SECONDS)) { System.out.println("主线程强制中断子线程!"); executorService.shutdownNow(); } System.out.println("主线程结束!"); } private void task(int index, CountDownLatch countDownLatch) { try { System.out.println("任务" + index); System.out.println(Thread.currentThread().getName() + " 开始工作!"); Thread.sleep((long) (Math.random() * 3000)); System.out.println(Thread.currentThread().getName() + " 工作结束!"); countDownLatch.countDown(); } catch (InterruptedException e) { System.out.println(Thread.currentThread().getName() + " 子线程中断!"); e.printStackTrace(); } }
运行结果:
任务1 任务3 任务4 pool-1-thread-4 开始工作! 任务2 pool-1-thread-2 开始工作! 任务5 pool-1-thread-3 开始工作! pool-1-thread-1 开始工作! pool-1-thread-5 开始工作! pool-1-thread-3 工作结束! pool-1-thread-2 工作结束! pool-1-thread-5 工作结束! pool-1-thread-4 工作结束! pool-1-thread-1 工作结束! 主线程结束!