Public interface Executor{
void execute(Runnable command);
}
Executor 基于生产者-消费者模式,将任务的提交过程和执行过程解耦开来,提交任务的操作相当于生产者(生产待完成的工作单元);执行任务的线程相当于消费者(执行完这些工作单元)。
线程池指管理一组同构工作线程的资源池。线程池与工作队列(Work Queue)密切相关。其中工作队列中保存了所有等待执行的任务。工作者线程的任务很简单:从工作队列中获取一个任务,执行任务,然后返回线程池并等待下一个任务。
Java类库提供了一个灵活的线程池以及一些有用的配置。可以通过调用Executors中的静态工厂方法来创建一个线程池:
通过使用Executor,可以实现各种调优、管理、监视、记录日志、错误报告和其他功能。
如何关闭Executor?如果不关闭Executor,那么JVM将永远不会结束(JVM在所有非守护线程结束后太会退出)。
为了解决执行服务的生命周期问题,Executor扩展了ExecutorService接口,添加了一些用于生命周期管理的方法。
ExecutorService 的生命周期有三种状态:运行、关闭和已终止。ExecutorService 在初始创建时处于运行状态。
Public interface ExecutorService extends Excutor{
void shutdown(); //执行平缓关闭过程----不再接收新任务,同时等待已提交任务的完成,包括队列中还未开始执行的任务
List<Runnable> shutdownNow(); //执行粗暴关闭过程----它尝试取消所有运行中的任务,并不在启动队列中尚未开始的任务
boolean isShutdown(); //判断是否关闭
boolean isTerminated(); //判断是否终止
boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedExecption; //等待终止
//其他用于任务提交的遍历方法
//…
}
Executor执行任务有4个生命周期阶段:创建、提交、开始和完成。由于一些任务可能需要执行很长时间,因此同行希望能够取消此类任务。Executor框架中:
一般在调用awaitTermnation之后立即调用shutdown,从而产生同步关闭ExectuorService的效果。
Executor使用Runnable作为其基本的任务表达形式。Runnable是一种有很大局限的抽象,虽然run能写入日志文件或者将结果放入某个共享的数据结构,但他不能返回一个值或者抛出一个受检查的异常。
Callable是一种更好的抽象:它认为主入口点(即call)将返回一个值,并可以抛出异常。
Future表示一个任务的生命周期,并提供了相应的方法来判断是否已经完成或者取消,以及获取任务的结果和取消任务等。
Public interface Callsble<V>{
V Call() throws Exception;
}
Public interface Future<V>{
boolean cancel (boolean mayInterruptIfRunning);
boolean isCancelled();
boolean isDone();
V get() throws InterruptedException, ExecutionException, CancellationException;
V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, CancellationException, TimeoutExecption;
}
ExecutorService中所有submit方法都将返回一个Future。将一个Runnable或Callable提交给Executor, 返回一个Future用来获得任务的执行结果或者取消任务。
完成任务(CompletionService):如果向Executor提交了一组计算任务,并希望在计算完成后获得结果。可以使用ExecutorService,获取返回的Future反复轮询get方法。但使用CompletionService更加方便。
CompletionService将Executor和BlockingQueue融合在一起。将执行的结果放入BlockingQueue中。然后用take和poll等方法获取完成后的结果。
ExecutorCompletionService实现了C欧美拍了体哦那Service,并将计算部分委托给一个Executor。
https://blog.csdn.net/chuan_yu_chuan/article/details/53390737 http://www.importnew.com/24923.html
什么时候会取消一个任务:
@ThreadSafe
Public class Test implements Runnable{
private volatile boolean cancelled;
public void run(){
while(!cancelled){
//具体逻辑
}
}
public void cancel(){ cancelled = true; }
}
包括三方面:
上面的任务取消有一个严重的问题:如果任务调用了一个阻塞方法,那么任务有可能永远不会检查取消标志,因此线程永远不会结束。比如生产者消费者模式中生产者的具体任务逻辑是:
blockingQueue.put(n++);
如果消费者执行效率远小于生产者效率,那么队列满时生产者线程将会阻塞。然后取消任务执行消费者线程被取消掉,那么生产者线程将会永远阻塞,无法检查取消标志。
所以应该使用任务中断方式。中断是实现取消的最合理的方式。
每个线程都有一个boolean类型的中断状态,当中断线程时,这个线程的中断状态将被置为true。
Public class Thread{
public void interrupt(){ … }
public boolean isInterrupted(){ … }
public static boolean interrupted(){ … }
…
}
对中断操作的正确理解是:它并不会真正地中断一个正在运行的线程,而只是发出中断请求,然后由线程在下一个合适的时刻中断自己。
Public class Test implements Runnable{
public void run(){
while(!Thread.currentThread().isInterrupted()){
//具体逻辑
}
}
public void cancel(){ interrupt(); }
}