public interface Executor {
void execute(Runnable command);
}
Executor基于生产者—消费者模式,用Runnable表示任务,提交任务操作相当于生产者,执行任务的线程相当于消费者
可通过Executors中的静态工厂方法创建线程池
使用ExecutorService管理生命周期,其包括运行、关闭、已终止
public interface ExecutorService extends Executor {
void shutdown();
List shutdownNow();
boolean isShutdown();
boolean isTerminated();
boolean awaitTermination(long timeout, TimeUnit unit)
throws InterruptedException;
Future submit(Callable task);
Future submit(Runnable task, T result);
Future> submit(Runnable task);
List> invokeAll(Collection extends Callable> tasks)
throws InterruptedException;
List> invokeAll(Collection extends Callable> tasks,
long timeout, TimeUnit unit)
throws InterruptedException;
T invokeAny(Collection extends Callable> tasks)
throws InterruptedException, ExecutionException;
T invokeAny(Collection extends Callable> tasks,
long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException;
......
}
Timer负责管理延迟任务和周期任务,但
故应该使用ScheduledThreadPoolExecutor代替Timer
相比于Runnable,Callable可以返回一个值或抛出一个异常
public interface Callable {
V call() throws Exception;
}
Future表示一个任务的生命周期,并提供方法判断任务是否完成、获取任务结果和取消任务等
public interface Future {
boolean cancel(boolean mayInterruptIfRunning);
boolean isCancelled();
boolean isDone();
V get() throws InterruptedException, ExecutionException;
V get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException;
}
CompletionService将Executor和BlockingQueue的功能结合,将Callable任务提交给它,然后用take()获取一个future的结果
通过设置取消标志,来取消任务执行
class MyTask implements Runnable {
private volatile boolean cancelled;
@Override
public void run() {
while (!cancelled) {
//......
}
}
public void cancel() {
cancelled = true;
}
}
但对于如下生产者-消费者模式,生产者添加队列的速度大于消费者,会导致put()阻塞,此时再调用cancel()也无法退出,因为消费者已停止(队列将一直阻塞)
class MyTask implements Runnable {
private volatile boolean cancelled;
private final BlockingQueue mQueue;
MyTask(BlockingQueue queue) {
this.mQueue = queue;
}
@Override
public void run() {
int i = 0;
while (!cancelled) {
try {
mQueue.put(i);
} catch (InterruptedException e) {
}
//......
}
}
public void consume() {
while (!cancelled){
try {
Thread.sleep(1000);
mQueue.take();
} catch (InterruptedException e) {
}
}
}
public void cancel() {
cancelled = true;
}
}
在Thread中
修改为Thread,while通过判断中断或put阻塞时抛出中断异常来退出线程
class MyTask extends Thread {
private final BlockingQueue mQueue;
MyTask(BlockingQueue queue) {
this.mQueue = queue;
}
@Override
public void run() {
int i = 0;
while (!Thread.currentThread().isInterrupted()) {
try {
mQueue.put(i);
} catch (InterruptedException e) {
}
//......
}
}
public void consume() {
while (!Thread.currentThread().isInterrupted()) {
try {
Thread.sleep(1000);
mQueue.take();
} catch (InterruptedException e) {
}
}
}
public void cancel() {
interrupt();
}
}
当调用可中断的阻塞函数时,如Thread.sleep或BlockingQueue
.put,有两种策略处理InterruptedException
class Task {
public void close() {
ExecutorService mExecutorService = Executors.newCachedThreadPool();
mExecutorService.execute(new Runnable() {
@Override
public void run() {
}
});
mExecutorService.shutdown();
try {
mExecutorService.awaitTermination(1000, TimeUnit.SECONDS);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
普通线程和守护线程的差异在于线程退出时发生的操作,当JVM中的普通线程都退出后,JVM会正常退出,如果仍存在守护线程则将被抛弃(不会执行finally)