JAVA和Nginx 教程大全

网站首页 > 精选教程 正文

Java 并发编程 11 - 异步执行框架 Executor

wys521 2024-11-19 12:53:21 精选教程 27 ℃ 0 评论

1 Executor 框架的简介


1.5 后引入的 Executor 框架的最大优点是把任务的提交和执行解耦。要执行任务的人只需把 Task 描述清楚,然后提交即可。这个 Task 是怎么被执行的,被谁执行的,什么时候执行的,提交的人就不用关心了。具体点讲,提交一个 Callable 对象给 ExecutorService(如最常用的线程池 ThreadPoolExecutor),将得到一个 Future 对象,调用 Future 对象的 get 方法等待执行结果就好了。


2 一个最简单的例子


看上去这个执行过程是这个样子。调用这段代码的是老大的老大了,他所需要干的所有事情就是找到一个合适的老大(如下面例子中 laodaA 就荣幸地被选中了),提交任务就好了。


        // 一个有7个作业线程的线程池,老大的老大找到一个管7个人的小团队的老大
		ExecutorService laodaA = Executors.newFixedThreadPool(7);
		// 提交作业给老大,作业内容封装在Callable中,约定好了输出的类型是String。
		String outputs = laoda.submit(new Callable<String>() {
			public String call() throws Exception {
				return "I am a task, which submited by the so called laoda, and run by those anonymous workers";
			}
			// 提交后就等着结果吧,到底是手下7个作业中谁领到任务了,老大是不关心的。
		}).get();

		System.out.println(outputs);


使用上非常简单,其实只有两行语句来完成所有功能:创建一个线程池,提交任务并等待获取执行结果。


3 Executor 框架的结构


Executor 框架主要由 3 大部分组成如下。


任务:包括被执行任务需要实现的接口:Runnable 接口或 Callable 接口。 任务的执行:包括任务执行机制的核心接口 Executor,以及继承自 Executor 的 ExecutorService 接口。Executor 框架有两个关键类实现了 ExecutorService 接口(ThreadPoolExecutor 和 ScheduledThreadPoolExecutor)。 异步计算的结果:包括接口 Future 和实现 Future 接口的 FutureTask 类。


Executor 框架包含的主要的类与接口如下图所示。



4 Executor 框架的接口简介


下面是这些类和接口的简介。


Executor 是一个接口,它是 Executor 框架的基础,它将任务的提交与任务的执行分离开来。 ThreadPoolExecutor 是线程池的核心实现类,用来执行被提交的任务。 ScheduledThreadPoolExecutor 是一个实现类,可以在给定的延迟后运行命令,或者定期执行命令。ScheduledThreadPoolExecutor 比 Timer 更灵活,功能更强大。 Future 接口和实现 Future 接口的 FutureTask 类,代表异步计算的结果。 Runnable 接口和 Callable 接口的实现类,都可以被 ThreadPoolExecutor 或 Scheduled-ThreadPoolExecutor 执行。它们之间的区别是 Runnable 不会返回结果,而 Callable 可以返回结果。


除了可以自己创建实现 Callable 接口的对象外,还可以使用工厂类 Executors 来把一个 Runnable 包装成一个 Callable。


下面是 Executors 提供的,把一个 Runnable 包装成一个 Callable 的 API。


public static Callable<Object> callable(Runnable task) // 假设返回对象Callable1


下面是 Executors 提供的,把一个 Runnable 和一个待返回的结果包装成一个 Callable 的 API。


public static <T> Callable<T> callable(Runnable task, T result) // 假设返回对象Call


前面讲过,当我们把一个 Callable 对象(比如上面的 Callable1 或 Callable2)提交给 ThreadPoolExecutor 或 ScheduledThreadPoolExecutor 执行时,submit(…)会向我们返回一个 FutureTask 对象。我们可以执行 FutureTask.get () 方法来等待任务执行完成。当任务成功完成后 FutureTask.get () 将返回该任务的结果。例如,如果提交的是对象 Callable1,FutureTask.get () 方法将返回 null;如果提交的是对象 Callable2,FutureTask.get () 方法将返回 result 对象。


5 Executor 框架的使用


Executor 框架的使用示意图如下图所示。



主线程首先要创建实现 Runnable 或者 Callable 接口的任务对象。工具类 Executors 可以把一个 Runnable 对象封装为一个 Callable 对象(Executors.callable(Runnable task)或 Executors.callable(Runnable task,Object resule))。

然后可以把 Runnable 对象直接交给 ExecutorService 执行(ExecutorService.execute(Runnablecommand));或者也可以把 Runnable 对象或 Callable 对象提交给 ExecutorService 执行(Executor-Service.submit(Runnable task)或 ExecutorService.submit(Callable<T>task))。

如果执行 ExecutorService.submit(…),ExecutorService 将返回一个实现 Future 接口的对象(到目前为止的 JDK 中,返回的是 FutureTask 对象)。由于 FutureTask 实现了 Runnable,程序员也可以创建 FutureTask,然后直接交给 ExecutorService 执行。

最后,主线程可以执行 FutureTask.get () 方法来等待任务执行完成。主线程也可以执行 FutureTask.cancel(boolean mayInterruptIfRunning)来取消此任务的执行。

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表