Executor框架
1.Task?Thread?
很多人在学习多线程这部分知识的时候,容易搞混两个概念:任务(task)和线程(thread)。
并发编程可以使我们的程序可以划分为多个分离的、独立运行的任务。而这些任务具体得由线程来驱动。Java中,Thread类自身不执行任何操作,它只是驱动赋予它的任务,任务由Runnable接口提供。
2.executor
Executor是个简单的接口,但它却提供了一种标准的方法将任务的提交过程与任务的执行过程解耦开来,从而无须太大困难就可以为某种类型的任务执行和修改执行策略。Executor基于生产者和消费者模式,提交任务的操作相当于生产者,执行任务的线程则相当于消费者。
3. 线程池
从字面上来讲,线程池就是管理一组同构工作线程(worker thread)的资源池。既然线程是负责驱动任务(task)的,那线程池就是用来处理一堆任务的,这堆任务通常存放在一个叫做工作队列(Working Queue)的地方。工作线程的任务很简单:从工作队列中获取一个任务,执行任务,然后返回线程池并等待下一个任务。
在Java中可使用java.util.concurrent.Executors类的静态工厂方法来创建一个线程池。
executor接口提供了任务提交和任务执行的分离的 标准。因此可以使用Executors创建不同的线程池,从而实现不同的执行策略。
4.ExecutorService
ExecutorService扩展了Executor接口,添加了一些用于生命周期管理的方法。
5.Runnable与Callable接口
Executor框架使用Runnable作为其基本的任务表示形式。但Runnable不会返回一个值或抛出一个受检查的异常。相反Callable可以返回一个值,并可能抛出一个异常。
6.Future与FutureTask
Future 表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并获取计算的结果。计算完成后只能使用 get 方法来获取结果,如有必要,计算完成前可以阻塞此方法。取消则由 cancel 方法来执行。还提供了其他方法,以确定任务是正常完成还是被取消了。
FutureTask 类是 Future 的一个实现,并且该类同时还实现了Runnable接口。
7.CompletionService接口
从功能上讲,CompletionService将Executor和BlockingQueue的功能融合在一起。将生产新的异步任务与使用已完成任务的结果分离开来的服务。生产者 submit 执行的任务。使用者 take 已完成的任务,并按照完成这些任务的顺序处理它们的结果。
如果不使用CompletionService,那每次Future.get的时候都要轮询来判断提交给Executor的任务是否完成。有了CompletionService的话直接take就好了。
ExecutorCompletionService类实现了该接口。