【读书笔记】《Java并发编程实战》第六章 Executor框架

Executor框架

一、什么是Executor框架?

为了把工作单元与执行机制分离开,Executor框架诞生了,他是一个用于统一创建与运行的接口。Executor框架实现的就是线程池的功能。

首先,我们先介绍Executor接口,如下示例:

//Executor接口
public interface Executor {
	void execute(Runnable command);
}

Executor接口提供的方法将任务的提交过程与执行过程解耦开来,并用Runnable来表示任务。

Executor基于生产者-消费者模式,提交任务的操作相当于生产者(生成待完成的任务),执行任务的线程则相当于消费者(执行完这些任务)。如果要再程序中实现一个生产者-消费者的设计,那么最简单的方式通常就是使用Executor。

二、Executor框架结构详解

Executor包括3大部分

  1. 任务:也就是工作单元,包括被执行任务需要实现的接口:Runnable接口或者Callable接口
  2. 任务的执行策略:也就是把任务分配给多线程之后的执行机制,包括Executor接口及继承自Executor接口的ExecutorService接口
  3. 异步计算任务的结果:包括Future接口及实现了Future接口的FutureTask类

Executor框架的成员关系图
Executor框架的成员关系图Executor或ExecutorService对象的实例化:
Executor以及ExecutorService可以通过调用Executors(注意不是Executor)的静态工厂方法来实例化。
Executors的静态工厂方法1.newFixedThreadPool: newFixedThreadPool将创建一个固定长度的线程池(ExecutorService对象),每当提交一个任务时就创建一个线程,直到达到线程池的最大数量,这时线程池的规模将不再变化。(如果某个线程由于发生未预期的Exception而结束,那么线程池会补充一个新的线程)
2.newCachedThreadPool: newCachedThreadPool将创建一个可缓存的线程池(ExecutorService对象),如果线程池的当前规模超过了处理需求时没那么将回收空闲的线程,而当需求增加时,则可以添加新的线程,线程池的规模不存在任何限制。
3.newSingleThreadExecutor: newSingleThreadExecutor是一个单线程的ExecutorService,它会创建单个工作者来执行任务,如果这个线程异常结束,会创建另一个线程来替代。newSingleThreadExecutor能确保依照任务在队列中的顺序来串行执行。
4.newScheduledThreadPool: newScheduledThreadPool创建了一个固定长度的线程池(ScheduledExecutorService对象),而且以延迟或者定时的方式来执行任务,类似Timer。

使用方法如下:

class Test {
	private static final Executor exec = Executors.newFixedThreadPool(100);

	public static void main(String []args) throws IOException {
		exec.execute(new Runnable() {
			@Override
			public void run() {
				System.out.println("GuYan");
			}
		});
	}
}

Executor的生命周期:
为了管理执行任务的生命周期,Executor拓展了ExecutorService接口,添加了一下用于生命周期管理的方法,如下程序段:

//ExecutorService中的生命周期管理方法
public interface ExecutorService extends Executor {
	void shutdown();//正常关闭ExecutorService 
	List<Runnable> shutdownNow();//强制关闭ExecutorService,使用时首先关闭正在执行的任务,然后返回所有尚未启动的任务清单
	boolean isShutdown();
	boolean isTerminated();
	boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException;
}

ExecutorService的生命周期有3种状态:运行、关闭和已终止

ExecutorService在初始创建时处于运行状态。shutdown方法将执行平缓的关闭过程:不再接受新的任务,同时等待已经提交的任务执行完成——包括那些还未开始执行的任务。shutdownNow方法将执行粗暴的关闭过程:它将尝试取消所有运行中的任务,并且不再启动队列中尚未开始执行的任务。

ExecutorService关闭后提交的任务将由“拒绝执行处理器”来处理,它会抛弃任务,或者使得execute方法抛出一个未检查的RejectedExecutionException。等所有任务都完成后,ExecutorService将转入终止状态

可以调用awaitTermination来等待ExecutorService到达终止状态,或者通过调用isTerminated来轮询ExecutorService是否已经终止。

通常在调用awaitTermination之后会立即调用shutdown,从而产生同步地关闭ExecutorService的效果

Executor框架的使用示意图
Executor框架的使用示意图框架使用步骤:

(1)创建Runnable并重写run()方法或者Callable对象并重写call()方法:

class callableTest implements Callable<String> {
	@Override
	public string call() {
		try {
			String name = "GuYan";
			return name;
		}
		catch (Execption e) {
			e.printStackTrace();
			return "exception";
		}
	}
}

(2)创建Executor接口的实现类ThreadPoolExecutor类或者ScheduledThreadPoolExecutor类的对象,然后调用其execute()方法或者submit()方法把工作任务添加到线程中,如果有返回值则返回Future对象

其中Callable对象有返回值,因此使用submit()方法;而Runnable可以使用execute()方法,此外还可以使用submit()方法,只要使用callable(Runnable task)或者callable(Runnable task, Object result)方法把Runnable对象包装起来就可以,使用callable(Runnable task)方法返回的null,使用callable(Runnable task, Object result)方法返回result。

ThreadPoolExecutor tpe = new ThreadPoolExecutor(5, 10,
                100, MILLISECONDS, new ArrayBlockingQueue<Runnable>(5));
Future<String> future = tpe.submit(new callableTest());

(3)调用Future对象的get()方法后返回call方法中的结果,或者调用Future对象的cancel()方法取消当前线程的执行,最后关闭线程池。

Executor执行的任务有4个生命周期阶段:创建提交开始完成

Executor框架中,已提交但尚未开始的任务可以取消,但对于那些已经开始执行的任务,只有当它们能响应中断时,才能取消。取消一个已经完成的任务不会有任何影响。

Future中get方法的行为取决于任务的状态(尚未开始、正在运行、已完成)。如果任务已经完成,那么get会立即返回或者抛出一个Exception。如果任务没有完成,那么get将阻塞并直到任务完成。

如果任务抛出了异常,那么Future中get将异常封装为ExecutionException并被get抛出。如果任务被取消,那么get将抛出CancellationException。如果get抛出了ExecutionException,那么可以通过Future中的getCause来获得被封装的初始异常。

try {
	System.out.println(future.get());
}
catch (Exception e) {
	e.printStackTrace();
}
finally {
	tpe.awaitTermination();
	tpe.shutdown();
}

三、Executor框架成员

Executor框架成员:ThreadPoolExecutor实现类、ScheduledThreadPoolExecutor实现类、Future接口、Runnable和Callable接口、Executors工厂类
Executor框架成员

猜你喜欢

转载自blog.csdn.net/Handsome_Le_le/article/details/107582893