思想
将"任务的提交"和"任务的执行"相分离,
执行服务 封装了任务执行的细节(线程创建、任务调度、线程关闭),
任务提交者而言,关注于任务本身(提交任务、获取结果、取消任务)
Future
提交者, 提交任务以后 得到一个Future, 用它可以去掉任务,获得结果 等
public interface Future<V> {
boolean cancel(boolean mayInterruptIfRunning);
boolean isCancelled();
boolean isDone();
//取结果
V get() throws InterruptedException, ExecutionException;
V get(long timeout, TimeUnit unit) throws InterruptedException,
ExecutionException, TimeoutException;
}
get方法,任务最终大概有三个结果:
- 正常完成
返回其执行结果,如果任务是Runnable且没有提供结果,返回null- 任务执行抛出了异常,
将异常包装为ExecutionException重新抛出,通过异常的getCause方法可以获取原异常- 任务被取消了,
抛出异常CancellationException
最简用法示例
public static void main(String[] args) throws InterruptedException,ExecutionException {
//创建了一个任务执行服务
ExecutorService executor = Executors.newSingleThreadExecutor();
//不管ExecutorService是如何创建的,对使用者而言,用法都一样
Future<Integer> future = executor.submit(new Task());
// 执行其他任务
System.out.println(future.get());
//关闭任务执行服务,不再接受新任务,
//但已提交的任务会继续执行
executor.shutdown();
}
使用了工厂类Executors创建了一个任务执行服务(Executors可创建多种执行服务,对任务提交者而言,都是一样使用)
关闭方法除了shutdown, 还有shutdownNow,
shutdownNow:马上终止,对于正在执行的任务,调用线程的interrupt方法尝试中断(不一定能成)会返回已提交但尚未执行的任务列表
ExecutorService接口
主要实现类是ThreadPoolExecutor,基于线程池的实现
继承最基本的Executor
public interface Executor {
void execute(Runnable command);
}
public interface ExecutorService extends Executor {
//提交任务
<T> Future<T> submit(Callable<T> task);
<T> Future<T> submit(Runnable task, T result);
Future<?> submit(Runnable task);//异步任务的最终返回值为null
//不接受新任务
void shutdown();
//已提交的都尽量停 返回没执行的
List<Runnable> shutdownNow();
boolean isShutdown();
boolean isTerminated();
boolean awaitTermination(long timeout, TimeUnit unit)
throws InterruptedException;
//全部执行完返回
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException;
//限时版,超时抛出异常
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)throws InterruptedException;
//有一个执行完就返回
<T> T invokeAny(Collection<? extends Callable<T>> tasks) throws InterruptedException, ExecutionException;
//限时版,超时抛出异常
<T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;
}
invokeAll使用例子:
public static void main(String[] args) throws InterruptedException {
//创建了一个线程池,这样使得多个任务可以并发执行
ExecutorService executor = Executors.newFixedThreadPool(10);
//2个任务
String url1 = "http://www.cnblogs.com/swiftma/p/5396551.html";
String url2 = "http://www.cnblogs.com/swiftma/p/5399315.html";
Collection<UrlTitleParser> tasks = Arrays.asList(
new UrlTitleParser[] {
new UrlTitleParser(url1),
new UrlTitleParser(url2)
});
//提交任务集合, 超过10秒就异常
List<Future<String>> results = executor.invokeAll(tasks, 10, TimeUnit.SECONDS);
for (Future<String> result : results) {
try {
//取结果 会等所有任务都完成 才能拿
System.out.println(result.get());
} catch (ExecutionException e) {
e.printStackTrace();
}
}
executor.shutdown();
}