Java线程池详解:ExecutorService接口及其实现类的创建与使用
本篇主要涉及到的是java.util.concurrent包中的ExecutorService。ExecutorService就是Java中对线程池的实现。

1。执行人员服务简介
执行人员服务是Java中线程池定义的接口。在Java.util.concrurnt软件包中,此接口中定义了与背景任务执行相关的方法:
执行人员服务接口有两个实现Java API,因此这两个是Java线程池特定的实现类(了解这两个实现类以获取详细信息,请单击此处):
1. ThreadPoolExecutor
2. ScheduledThreadPoolExecutor
此外,执行人员服务还继承了执行程序界面(请注意,它在执行程序接口和执行者出厂类别之间有区别)。此接口仅具有一个execute()方法。最后,让我们看一下整个继承树:
2。执行人员服务的创建
需要根据特定的应用程序方案确定哪种类型的执行权限实例(IE线程池)。但是,Java为我们提供了执行者工厂类别,该类可以帮助我们轻松创建各种类型的执行人员服务线程池。执行者总共可以创建以下四种线程池:
1. newCachedThreadPool 创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
2. newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
3. newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
4. newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
注意:执行者只是工厂课程。其所有方法返回两个类的实例:ThreadPoolExecutor和ScheduleDthReadPoolExecutor。
3。使用执行人员服务
ExecutorService executorService = Executors.newFixedThreadPool(10);
executorService.execute(new Runnable() {
public void run() {
System.out.println("Asynchronous task");
}
});
executorService.shutdown();
4。执行执行权限服务
执行人员服务具有以下执行方法:
- execute(Runnable)
- submit(Runnable)
- submit(Callable)
- invokeAny(...)
- invokeAll(...)
4.1执行(可运行)
此方法接收一个可运行的实例并异步执行。请参阅以下示例:
ExecutorService executorService = Executors.newSingleThreadExecutor();
executorService.execute(new Runnable() {
public void run() {
System.out.println("Asynchronous task");
}
});
executorService.shutdown();
这种方法存在问题,即无法知道任务的执行结果。如果我们想获得任务的执行结果,则可以通过可调用的实例传递(如下所述)。
4.2提交(可运行)
提交(运行)和执行(可运行)之间的区别在于,前者可以返回未来的对象。通过返回的未来对象,我们可以检查提交的任务是否已执行。请参阅以下执行示例:
Future future = executorService.submit(new Runnable() {
public void run() {
System.out.println("Asynchronous task");
}
});
future.get(); //returns null if the task has finished correctly.
如果任务执行完成,则Future.get()方法将返回null。请注意,future.get()方法将导致阻塞。
4.3提交(可可)
提交(可召唤)和提交(可运行)与此相似,它们还将返回将来的对象。但是,此外,提交(可召唤)也会收到可调用的实现。可可接口中的call()方法具有返回值,该值可以返回任务的执行结果,并且可运行接口中的run()方法是无效的,没有返回值。请参阅以下示例:
Future future = executorService.submit(new Callable(){
public Object call() throws Exception {
System.out.println("Asynchronous Callable");
return "Callable Result";
}
});
System.out.println("future.get() = " + future.get());
如果任务执行完成,则Future.get()方法将返回可callable任务的执行结果。请注意,future.get()方法将导致阻塞。
4.4 Invokeany(…)
Invokeany(...)方法收到了可可的集合。执行此方法将不会返回将来,但将返回所有可召唤任务中一项任务的执行结果。此方法无法保证返回哪个任务的执行结果,无论如何,它是其中之一。请参阅以下示例:
ExecutorService executorService = Executors.newSingleThreadExecutor();
Set> callables = new HashSet>();
callables.add(new Callable() {
public String call() throws Exception {
return "Task 1";
}
});
callables.add(new Callable() {
public String call() throws Exception {
return "Task 2";
}
});
callables.add(new Callable() {
public String call() throws Exception {
return "Task 3";
}
});
String result = executorService.invokeAny(callables);
System.out.println("result = " + result);
executorService.shutdown();
您可以尝试执行上述代码。每个执行将返回结果,并更改返回的结果,并可能返回“ task2”或“ task1”或其他结果。
4.5 InvokeAll(…)
InvokeAll(...)类似于Invokeany(...),也会收到一个可召集的集合,但是在执行前者后,它返回了未来列表,该列表与执行每个可召唤任务后对应于未来对象。以下示例:
ExecutorService executorService = Executors.newSingleThreadExecutor();
Set> callables = new HashSet>();
callables.add(new Callable() {
public String call() throws Exception {
return "Task 1";
}
});
callables.add(new Callable() {
public String call() throws Exception {
return "Task 2";
}
});
callables.add(new Callable() {
public String call() throws Exception {
return "Task 3";
}
});
List> futures = executorService.invokeAll(callables);
for(Future future : futures){
System.out.println("future.get = " + future.get());
}
executorService.shutdown();
5。执行人员服务关闭
当我们完成执行人员服务时,应关闭它,否则内部的线程将处于运行状态。
例如,如果通过main()方法启动了应用程序,则在main()退出之后,如果应用程序中的执行权限未关闭,则该应用程序将继续运行。之所以发生这种情况,是因为在执行人员服务中运行的线程阻止JVM关闭。
如果要关闭在执行人员服务中执行的线程,我们可以调用executorService.shutdown()方法。调用shutdown()方法后,执行程序服务不会立即关闭,但是它不再接收新任务,并且在所有线程当前执行之前都不会关闭。在关闭()之前提交的所有任务将执行。
如果我们想立即关闭执行人员服务,我们可以调用executorService.shutdownnow()方法。此操作将跳过正在执行的所有任务和尚未执行的任务。但这不能保证执行的任务保证。他们可能会停止或可能被执行。
有关Java线程池类ThreadPoolExecutor,ScheduledthreadPoolexecutor和执行者出厂类的更详细介绍,请单击此处