线程池相关
源码:
package java.util.concurrent;
import java.util.List;
import java.util.Collection;
public interface ExecutorService extends Executor {
//启动一次顺序关闭,执行以前提交的任务,但不接受新任务
void shutdown();
//试图停止所有正在执行的活动任务,暂停处理正在等待的任务,并返回等待执行的任务列表
List<Runnable> shutdownNow();
//如果此执行程序已关闭,则返回 true
boolean isShutdown();
//如果关闭后所有任务都已完成,则返回 true
boolean isTerminated();
//阻塞当前线程:直到所有任务执行完毕、等待超时或者当前线程中断,才会返回
boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException;
//提交一个返回值的任务用于执行,返回一个表示任务的未决结果的 Future
<T> Future<T> submit(Callable<T> task);
//提交一个 Runnable 任务用于执行,并返回一个表示该任务的 Future
Future<?> submit(Runnable task);
//提交一个 Runnable 任务用于执行,并返回一个表示该任务的 Future
<T> Future<T> submit(Runnable task, T result);
//执行给定的任务,当所有任务完成时,返回保持任务状态和结果的 Future 列表
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException;
// 执行给定的任务,当所有任务完成或超时期满时(无论哪个首先发生),返回保持任务状态和结果的 Future 列表
<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;
}
接口 ExecutorService
父接口:
已知子接口:
已知实现类:
AbstractExecutorService, ScheduledThreadPoolExecutor, ThreadPoolExecutor
Executors
类提供了用于此包中所提供的执行程序服务的工厂方法。
提供两个方法来关闭 ExecutorService:
shutdown()
方法在终止前允许执行以前提交的任务;无法提交新任务。
shutdownNow()
方法阻止等待任务启动并试图停止当前正在执行的任务。没有任务在等待执行,并且无法提交新任务,执行中的任务将会收到中断信号。
从父接口,继承得到的 execute(Runnable command) 方法,只能执行Runnable类型的线程,而且还不能得到返回值。在ExecutorService 中 submit() 通过返回一个可获取返回值的 Future,不仅支持了执行Runnable类型的线程,也支持了Callable的线程执行。
invokeAny() 和 invokeAll() 是批量执行的最常用形式,它们执行任务 collection,然后等待至少一个,或全部任务完成(可使用 ExecutorCompletionService
类来编写这些方法的自定义变体)。
例如,AbstractExecutorService中invokeAny(Collection<? extends Callable<T>> tasks):
public <T> T invokeAny(Collection<? extends Callable<T>> tasks)
throws InterruptedException, ExecutionException {
try {
return doInvokeAny(tasks, false, 0);//执行上述的私有方法
} catch (TimeoutException cannotHappen) {
assert false;
return null;
}
}
其中的doInvokeAny方法:
private <T> T doInvokeAny(Collection<? extends Callable<T>> tasks,
boolean timed, long nanos)
throws InterruptedException, ExecutionException, TimeoutException {
if (tasks == null)
throw new NullPointerException();
int ntasks = tasks.size();
if (ntasks == 0)
throw new IllegalArgumentException();
List<Future<T>> futures= new ArrayList<Future<T>>(ntasks);
// ExecutorCompletionService负责执行任务,后面调用用poll返回第一个执行结果
ExecutorCompletionService<T> ecs = new ExecutorCompletionService<T>(this);
// 这里出于效率的考虑,每次提交一个任务之后,就检查一下有没有执行完成的任务
try {
ExecutionException ee = null;
long lastTime = timed ? System.nanoTime() : 0;
Iterator<? extends Callable<T>> it = tasks.iterator();
// 先提交一个任务
futures.add(ecs.submit(it.next()));
--ntasks;
int active = 1;
for (;;) {
// 尝试获取有没有执行结果(这个结果是立刻返回的)
Future<T> f = ecs.poll();
// 没有执行结果
if (f == null) {
// 如果还有任务没有被提交执行的,就再提交一个任务
if (ntasks > 0) {
--ntasks;
futures.add(ecs.submit(it.next()));
++active;
}
// 没有任务在执行了,而且没有拿到一个成功的结果。
else if (active == 0)
break;
// 如果设置了超时情况
else if (timed) {
// 等待执行结果直到有结果或者超时
f = ecs.poll(nanos, TimeUnit.NANOSECONDS);
if (f == null)
throw new TimeoutException();
// 这里的更新不可少,因为这个Future可能是执行失败的情况,那么还需要再次等待下一个结果,超时的设置还是需要用到。
long now = System.nanoTime();
nanos -= now - lastTime;
lastTime = now;
}
// 没有设置超时,并且所有任务都被提交了,则一直等到第一个执行结果出来
else
f = ecs.take();
}
// 有返回结果了,尝试从future中获取结果,如果失败了,那么需要接着等待下一个执行结果
if (f != null) {
--active;
try {
return f.get();
} catch (ExecutionException eex) {
ee = eex;
} catch (RuntimeException rex) {
ee = new ExecutionException(rex);
}
}
}
// ExecutorCompletionService执行时发生错误返回了全是null的future
if (ee == null)
ee = new ExecutionException();
throw ee;
} finally {
// 尝试取消所有的任务(对于已经完成的任务没有影响)
for (Future<T> f : futures)
f.cancel(true);
}
}
当所有的任务被提交后,任务执行返回的Future会被依次添加到一个BlockingQueue中,然后找到第一个执行成功任务的方法就是从BlockingQueue取出第一个元素,这个就是doInvokeAny方法用到的ExecutorCompletionService的基本原理。
shutdown
void shutdown()
启动一次顺序关闭,执行以前提交的任务,但不接受新任务。如果已经关闭,则调用没有其他作用。
抛出:
SecurityException
- 如果安全管理器存在并且关闭,此 ExecutorService 可能操作某些不允许调用者修改的线程(因为它没有保持 RuntimePermission
("modifyThread")),或者安全管理器的 checkAccess 方法拒绝访问。
shutdownNow
List<Runnable> shutdownNow()
试图停止所有正在执行的活动任务,暂停处理正在等待的任务,并返回等待执行的任务列表。
无法保证能够停止正在处理的活动执行任务,但是会尽力尝试。例如,通过 Thread.interrupt()
来取消典型的实现,所以无法响应中断的任务可能将永远无法终止。
返回:
从未开始执行的任务的列表
抛出:
SecurityException
- 如果安全管理器存在并且关闭,此 ExecutorService 可能操作某些不允许调用者修改的线程(因为它没有保持 RuntimePermission
("modifyThread")),或者安全管理器的 checkAccess 方法拒绝访问。
isShutdown
boolean isShutdown()
如果此执行程序已关闭,则返回 true。
返回:
如果此执行程序已关闭,则返回 true
isTerminated
boolean isTerminated()
如果关闭后所有任务都已完成,则返回 true。注意,除非首先调用 shutdown 或 shutdownNow,否则 isTerminated 永不为 true。
返回:
如果关闭后所有任务都已完成,则返回 true
awaitTermination
boolean awaitTermination(long timeout,TimeUnit unit) throws InterruptedException
阻塞当前线程:直到所有任务执行完毕、等待超时或者当前线程中断,才会返回。
一般在调用shutdown()方法后调用,用来检测 timeout 时间后线程池是否关闭。
参数:
timeout
- 最长等待时间
unit
- timeout 参数的时间单位
返回:
如果此执行程序终止,则返回 true;如果终止前超时期满,则返回 false
抛出:
InterruptedException
- 如果等待时发生中断
submit
<T> Future<T> submit(Callable<T> task)
提交一个返回值的任务用于执行,返回一个表示任务的未决结果的 Future。该 Future 的 get 方法在成功完成时将会返回该任务的结果。
如果想立即阻塞任务的等待,则可以使用 result = exec.submit(aCallable).get(); 形式的构造。
注:Executors
类包括了一组方法,可以转换某些其他常见的类似于闭包的对象,例如,将 PrivilegedAction
转换为 Callable
形式,这样就可以提交它们了。
参数:
task
- 要提交的任务
返回:
表示任务等待完成的 Future
抛出:
RejectedExecutionException
- 如果任务无法安排执行
NullPointerException
- 如果该任务为 null
submit
<T> Future<T> submit(Runnable task, T result)
提交一个 Runnable 任务用于执行,并返回一个表示该任务的 Future。该 Future 的 get 方法在成功完成时将会返回给定的结果。
参数:
task
- 要提交的任务
result
- 返回的结果
返回:
表示任务等待完成的 Future
抛出:
RejectedExecutionException
- 如果任务无法安排执行
NullPointerException
- 如果该任务为 null
submit
Future<?> submit(Runnable task)
提交一个 Runnable 任务用于执行,并返回一个表示该任务的 Future。该 Future 的 get 方法在 成功 完成时将会返回 null。
参数:
task
- 要提交的任务
返回:
表示任务等待完成的 Future
抛出:
RejectedExecutionException
- 如果任务无法安排执行
NullPointerException
- 如果该任务为 null
invokeAll
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException
执行给定的任务,当所有任务完成时,返回保持任务状态和结果的 Future 列表。返回列表的所有元素的 Future.isDone()
为 true。注意,可以正常地或通过抛出异常来终止 已完成 任务。如果正在进行此操作时修改了给定的 collection,则此方法的结果是不确定的。
参数:
tasks
- 任务 collection
返回:
表示任务的 Future 列表,列表顺序与给定任务列表的迭代器所生成的顺序相同,每个任务都已完成。
抛出:
InterruptedException
- 如果等待时发生中断,在这种情况下取消尚未完成的任务。
NullPointerException
- 如果任务或其任意元素为 null
RejectedExecutionException
- 如果所有任务都无法安排执行
invokeAll
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,long timeout,TimeUnit unit) throws InterruptedException
执行给定的任务,当所有任务完成或超时期满时(无论哪个首先发生),返回保持任务状态和结果的 Future 列表。返回列表的所有元素的 Future.isDone()
为 true。一旦返回后,即取消尚未完成的任务。注意,可以正常地或通过抛出异常来终止 已完成 任务。如果此操作正在进行时修改了给定的 collection,则此方法的结果是不确定的。
参数:
tasks
- 任务 collection
timeout
- 最长等待时间
unit
- timeout 参数的时间单位
返回:
表示任务的 Future 列表,列表顺序与给定任务列表的迭代器所生成的顺序相同。如果操作未超时,则已完成所有任务。如果确实超时了,则某些任务尚未完成。
抛出:
InterruptedException
- 如果等待时发生中断,在这种情况下取消尚未完成的任务
NullPointerException
- 如果任务或其任意元素或 unit 为 null
RejectedExecutionException
- 如果所有任务都无法安排执行
invokeAny
<T> T invokeAny(Collection<? extends Callable<T>> tasks) throws InterruptedException,ExecutionException
执行给定的任务,如果某个任务已成功完成(也就是未抛出异常),则返回其结果。一旦正常或异常返回后,则取消尚未完成的任务。如果此操作正在进行时修改了给定的 collection,则此方法的结果是不确定的。
参数:
tasks
- 任务 collection
返回:
某个任务返回的结果
抛出:
InterruptedException
- 如果等待时发生中断
NullPointerException
- 如果任务或其任意元素为 null
IllegalArgumentException
- 如果任务为空
ExecutionException
- 如果没有任务成功完成
RejectedExecutionException
- 如果任务无法安排执行
invokeAny
<T> T invokeAny(Collection<? extends Callable<T>> tasks,long timeout,TimeUnit unit) throws InterruptedException,ExecutionException,TimeoutException
执行给定的任务,如果在给定的超时期满前某个任务已成功完成(也就是未抛出异常),则返回其结果。一旦正常或异常返回后,则取消尚未完成的任务。如果此操作正在进行时修改了给定的 collection,则此方法的结果是不确定的。
参数:
tasks
- 任务 collection
timeout
- 最长等待时间
unit
- timeout 参数的时间单位
返回:
某个任务返回的结果
抛出:
InterruptedException
- 如果等待时发生中断
NullPointerException
- 如果任务或其任意元素或 unit 为 null
TimeoutException
- 如果在所有任务成功完成之前给定的超时期满
ExecutionException
- 如果没有任务成功完成
RejectedExecutionException
- 如果任务无法安排执行
调用实例:
- invokeAny取得第一个方法的返回值,当第一个任务结束后,会调用interrupt方法中断其它任务。
- invokeAll等线程任务执行完毕后,取得全部任务的结果值。
invokeAll(tasks):
package com.thread;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class InvokeAllTest implements Callable<String> {
int a = 0;
public InvokeAllTest(int a){
this.a=a;
}
@Override
public String call(){
System.out.println("当前值为:" + a);
return Integer.toString(a);
}
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(3);
List<Callable<String>> list = new ArrayList<>();
for (int i = 0; i < 5; i++) {
list.add(new InvokeAllTest(i));
}
try {
List<Future<String>> futures = executorService.invokeAll(list);
for (Future<String> future : futures) {
System.out.println("返回值:"+future.get());
}
} catch (InterruptedException e) {//invokeAll 可能抛出的异常
e.printStackTrace();
} catch (ExecutionException e) {//future.get() 可能抛出的异常
e.printStackTrace();
}
executorService.shutdown();
}
}
运行结果:
当前值为:0
当前值为:2
当前值为:3
当前值为:4
当前值为:1
返回值:0
返回值:1
返回值:2
返回值:3
返回值:4
如果在call方法中抛出异常了,只有在main方法调用了future.get(),main线程才能捕获到异常:
1.不调用future.get():
package com.thread;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class InvokeAllTest implements Callable<String> {
int a = 0;
public InvokeAllTest(int a) {
this.a = a;
}
@Override
public String call(){
System.out.println("当前值为:" + a);
if (a == 2) {
throw new RuntimeException();
}
return Integer.toString(a);
}
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(3);
List<Callable<String>> list = new ArrayList<>();
for (int i = 0; i < 5; i++) {
list.add(new InvokeAllTest(i));
}
try {
executorService.invokeAll(list);
} catch (InterruptedException e) {//invokeAll 可能抛出的异常
e.printStackTrace();
}
executorService.shutdown();
}
}
运行结果:
当前值为:0
当前值为:1
当前值为:3
当前值为:4
当前值为:2
调用 future.get():
package com.thread;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class InvokeAllTest implements Callable<String> {
int a = 0;
public InvokeAllTest(int a) {
this.a = a;
}
@Override
public String call(){
System.out.println("当前值为:" + a);
if (a == 2) {
throw new RuntimeException();
}
return Integer.toString(a);
}
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(3);
List<Callable<String>> list = new ArrayList<>();
for (int i = 0; i < 5; i++) {
list.add(new InvokeAllTest(i));
}
try {
List<Future<String>> futures = executorService.invokeAll(list);
for (Future<String> future : futures) {
System.out.println("返回值:" + future.get());
}
} catch (InterruptedException e) {//invokeAll 可能抛出的异常
e.printStackTrace();
} catch (ExecutionException e) {//future.get() 可能抛出的异常
e.printStackTrace();
}
executorService.shutdown();
}
}
运行结果:
当前值为:0
当前值为:2
当前值为:1
当前值为:4
当前值为:3
返回值:0
返回值:1
java.util.concurrent.ExecutionException: java.lang.RuntimeException
at java.util.concurrent.FutureTask.report(FutureTask.java:122)
at java.util.concurrent.FutureTask.get(FutureTask.java:192)
at com.thread.InvokeAllTest.main(InvokeAllTest.java:37)
Caused by: java.lang.RuntimeException
at com.thread.InvokeAllTest.call(InvokeAllTest.java:22)
at com.thread.InvokeAllTest.call(InvokeAllTest.java:11)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
invokeAll(tasks,timeout,unit)):若在指定时间内任务没有执行完毕,则interrupt 中断线程的执行;需要注意:此时无法获取到任何异常,只有当在Future对象调用get()方法时,才会抛出 CancellationException 异常。
将上述例子:
executorService.invokeAll(list);
修改为:
executorService.invokeAll(list, 15, TimeUnit.SECONDS);
若在call()中有异常抛出,只有在main方法调用了future.get(),main线程才能捕获到异常。
invokeAny(tasks):
package com.thread;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class InvokeAllTest implements Callable<String> {
int a = 0;
public InvokeAllTest(int a) {
this.a = a;
}
@Override
public String call() {
System.out.println("当前值为:" + a);
return Integer.toString(a);
}
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(3);
List<Callable<String>> list = new ArrayList<>();
for (int i = 0; i < 5; i++) {
list.add(new InvokeAllTest(i));
}
try {
String value = executorService.invokeAny(list);
System.out.println("最后结果值是======:" + value);
} catch (InterruptedException e) {//invokeAll 可能抛出的异常
e.printStackTrace();
} catch (ExecutionException e) {//future.get() 可能抛出的异常
e.printStackTrace();
}
executorService.shutdown();
}
}
运行结果:
当前值为:0
当前值为:2
当前值为:3
当前值为:1
最后结果值是======:0
当前值为:4
invokeAny取得了某一个线程返回的值之后,但是其他线程仍将继续运行,直到运行结束。
如果任意一个任务在call()抛出了异常,并且异常没有在call()中被显示捕获处理,那么控制台将不会打印任何异常信息。
package com.thread;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class InvokeAllTest implements Callable<String> {
int a = 0;
public InvokeAllTest(int a) {
this.a = a;
}
@Override
public String call() throws Exception{
if (a>0) {
throw new Exception("error");
}
System.out.println("当前值为:" + a);
return Integer.toString(a);
}
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(3);
List<Callable<String>> list = new ArrayList<>();
for (int i = 0; i < 5; i++) {
list.add(new InvokeAllTest(i));
}
try {
String value = executorService.invokeAny(list);
System.out.println("最后结果值是======:" + value);
} catch (InterruptedException e) {//invokeAll 可能抛出的异常
e.printStackTrace();
} catch (ExecutionException e) {//future.get() 可能抛出的异常
e.printStackTrace();
}
executorService.shutdown();
}
}
运行结果:
当前值为:0
最后结果值是======:0
若所有的任务都发生异常,那么将返回最后一个异常并且输出异常信息,最终在ExecutionException中被捕获:
package com.thread;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class InvokeAllTest implements Callable<String> {
int a = 0;
public InvokeAllTest(int a) {
this.a = a;
}
@Override
public String call() throws Exception{
if (a>-1) {
throw new Exception("error");
}
System.out.println("当前值为:" + a);
return Integer.toString(a);
}
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(3);
List<Callable<String>> list = new ArrayList<>();
for (int i = 0; i < 5; i++) {
list.add(new InvokeAllTest(i));
}
try {
String value = executorService.invokeAny(list);
System.out.println("最后结果值是======:" + value);
} catch (InterruptedException e) {//invokeAll 可能抛出的异常
e.printStackTrace();
} catch (ExecutionException e) {//future.get() 可能抛出的异常
e.printStackTrace();
}
executorService.shutdown();
}
}
运行结果:
java.util.concurrent.ExecutionException: java.lang.Exception: error
at java.util.concurrent.FutureTask.report(FutureTask.java:122)
at java.util.concurrent.FutureTask.get(FutureTask.java:192)
at java.util.concurrent.AbstractExecutorService.doInvokeAny(AbstractExecutorService.java:193)
at java.util.concurrent.AbstractExecutorService.invokeAny(AbstractExecutorService.java:215)
at com.thread.InvokeAllTest.main(InvokeAllTest.java:33)
Caused by: java.lang.Exception: error
at com.thread.InvokeAllTest.call(InvokeAllTest.java:20)
at com.thread.InvokeAllTest.call(InvokeAllTest.java:10)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
invokeAny(tasks,timeout,unit)):在指定时间内取得第一个先执行完任务的结果值,如果超时,则抛出TimeoutException,并且interrupt线程。
将上述例子:
executorService.invokeAny(list);
修改为:
executorService.invokeAny(list, 15, TimeUnit.SECONDS);
综合解读
Executor接口非常单一,就是执行一个Runnable的命令。
public interface Executor {
void execute(Runnable command);
}
ExecutorService接口扩展了Executor接口,增加状态控制,执行多个任务返回Future。
关于状态控制的方法:
// 发出关闭信号,不会等到现有任务执行完成再返回,但是现有任务还是会继续执行,
// 可以调用awaitTermination等待所有任务执行。不再接受新的任务。
void shutdown();
// 立刻关闭,尝试取消正在执行的任务(不保证会取消成功),返回未被执行的任务
List<Runnable> shutdownNow();
// 是否发出关闭信号
boolean isShutdown();
// 是否所有任务都执行完毕在shutdown之后,也就是如果不调用shutdownNow或者
// shutdown是不可能返回true
boolean isTerminated();
// 进行等待直到所有任务完成或者超时
boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException;
提交单个任务,立刻返回一个Future存储任务执行的实时状态
<T> Future<T> submit(Callable<T> task);
<T> Future<T> submit(Runnable task, T result);
Future<?> submit(Runnable task);
执行多个任务的方法,有两种方式,一种等到所有任务执行完成才返回:
<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;
通过上面的代码可以看出ExecutorService可以执行两种类型的任务:Runnable和Callable,而Callable用的更加多。两者区别很简单,前者不会返回执行结果而后者会返回一个执行结果:
public interface Callable<V> {
V call() throws Exception;
}
接着说说Future,也就是执行任务的返回类型。
Future可以看成是一张发票。比如你送件衣服到洗衣店清洗,他们会开张发票给你,你拿着发票可以去拿回你洗好的衣服或者去洗衣店问衣服是否洗好了等等。
public interface Future<V> {
//取消任务,参数mayInterruptIfRunning为true时,如果要取消的任务正在执行,
//会把执行这个任务的线程设为中断,为false时,正在执行的任务会被允许执行完成
boolean cancel(boolean mayInterruptIfRunning);
boolean isCancelled();
boolean isDone();
//获取执行结果,如果任务执行中,会等到任务完成再返回
V get() throws InterruptedException, ExecutionException;
V get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException;
}
最后看看ScheduledExecutorService接口,该接口是ExecutorService的子接口,增加了定时执行任务的功能:
public interface ScheduledExecutorService extends ExecutorService {
public ScheduledFuture<?> schedule(Runnable command,
long delay, TimeUnit unit);
public <V> ScheduledFuture<V> schedule(Callable<V> callable,
long delay, TimeUnit unit);
// 等待一定时间然后开始执行一个任务,每隔period参数设置的时间
// 重复一次,(多线程执行)
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
long initialDelay,
long period,
TimeUnit unit);
// 等待一定时间然后开始执行一个任务,完成后,等待delay参数设置的时间
// 然后在执行一次任务。(单线程执行)
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
long initialDelay,
long delay,
TimeUnit unit);
}