线程池相关
源码:
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
提供两个方法来关闭 ExecutorService:
shutdown()
方法在终止前允许执行以前提交的任务;无法提交新任务。
shutdownNow()
方法阻止等待任务启动并试图停止当前正在执行的任务。没有任务在等待执行,并且无法提交新任务,执行中的任务将会收到中断信号。
从父接口,继承得到的 execute(Runnable command) 方法,只能执行Runnable类型的线程,而且还不能得到返回值。在ExecutorService 中 submit() 通过返回一个可获取返回值的 Future,不仅支持了执行Runnable类型的线程,也支持了Callable的线程执行。
invokeAny() 和 invokeAll() 是批量执行的最常用形式,它们执行任务 collection,然后等待至少一个,或全部任务完成(可使用 ExecutorCompletionService
类来编写这些方法的自定义变体)。
Executors
类提供了用于此包中所提供的执行程序服务的工厂方法。
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);