接下来我会为你详细讲解 “理解Java多线程中ExecutorService使用”的完整攻略。
1. ExecutorService 是什么?
ExecutorService 接口是 Java 并发 API 提供的一个线程池管理器。它可以管理一个池子中的线程数量,也可以通过合理配置线程池中的参数,来提高系统的吞吐量和性能。
2. ExecutorService 线程池的种类
ExecutorService 已经有很多不同的实现类了,其中常用的有以下几种:
2.1. FixedThreadPool
FixedThreadPool(固定大小线程池)是指在初始化线程池的时候设置线程数目,线程数目不会变化。
2.2. CachedThreadPool
CachedThreadPool(缓存线程池)是指在运行的过程中,根据需要创建新的线程,当线程超过一定时间没有被使用,就自动销毁。
2.3. SingleThreadPool
SingleThreadPool(单线程池)是指只有一个核心线程,也就是线程池的最大容量为 1。通常用于这种场景:需要处理逐一处理任务,而不是并发的处理任务。
2.4. ScheduledThreadPool
ScheduledThreadPool(定时任务线程池)是指在固定时间间隔内执行定时任务线程池。
3. ExecutorService 的使用方法
首先,在使用 Runnable 或者 Callable 作为 Thread 的构造函数的时候,我们可以将这些的目标作为 向Executor提交的任务(Task)
public class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("MyRunnable");
}
}
public class Main{
public static void main(String args[]){
ExecutorService threadPool = Executors.newFixedThreadPool(5);
threadPool.execute(new MyRunnable()); // 向线程池提交任务
}
4. ExecutorService 中 submit 方法和 execute 方法的区别
submit 方法和 execute 方法都可以向线程池提交任务,但是他们还是存在一定的区别:
- submit 方法会【返回一个 Future】,这个 Future 可以操作刚提交的 Task 的结果
public class MyCallable implements Callable {
@Override
public Object call() throws Exception {
System.out.println("MyCallable");
return "result";
}
}
public class Main {
public static void main(String[] args) {
ExecutorService executorService = Executors.newSingleThreadExecutor();
Future<String> future = executorService.submit(new MyCallable());
try {
String result = future.get(); // 拿到 callable 的结果
System.out.println(result); // 打印结果
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}
- execute 方法则不会返回结果。
public class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("MyRunnable");
}
}
public class Main {
public static void main(String args[]){
ExecutorService threadPool = Executors.newFixedThreadPool(5);
threadPool.execute(new MyRunnable());
threadPool.shutdown(); //关闭线程池
}
}
5. ExecutorService 的关闭
当我们使用完 ExecutorService 线程池之后,需要进行关闭。
这时,我们可以使用 shutdown 方法进行关闭,如下所示。
public class Main {
public static void main(String args[]){
ExecutorService threadPool = Executors.newFixedThreadPool(5);
threadPool.execute(new MyRunnable());
threadPool.shutdown(); //关闭线程池
}
}
6. 示例说明
6.1. 示例1:Runnable 使用 ExecutorService
下面的代码演示了 Runnable 如何使用 ExecutorService。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Main {
public static void main(String args[]){
ExecutorService threadPool = Executors.newFixedThreadPool(5);
for (int i = 0;i<5;i++){
MyRunnable myRunnable = new MyRunnable();
threadPool.execute(myRunnable);
}
threadPool.shutdown();
}
}
class MyRunnable implements Runnable {
public void run() {
System.out.println(Thread.currentThread().getName() + " 正在执行 task.");
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
代码说明:
- 这里我们首先创建一个 ExecutorService 对象 threadPool,它是一个 FixedThreadPool 类型的线程池,最大线程数为 5。
- 然后我们创建 5 个需要执行的 Task(Runable),然后分别通过 ExecutorService 来 管理它们的执行。
- 最后通过 threadPool.shutdown() 方法等待所有的 Task 都已经执行完成,然后关闭这个ExecutorService。
输出结果如下:
pool-1-thread-1 正在执行 task.
pool-1-thread-2 正在执行 task.
pool-1-thread-3 正在执行 task.
pool-1-thread-4 正在执行 task.
pool-1-thread-5 正在执行 task.
6.2. 示例2:Callable 使用 ExecutorService
下面的代码则演示了 Callable 如何使用 ExecutorService:
import java.util.ArrayList;
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 Main {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService executorService = Executors.newFixedThreadPool(2);
ArrayList<Future<String>> futureList = new ArrayList<>();
for(int i=0;i<10;i++){
MyTask myTask = new MyTask(i);
futureList.add(executorService.submit(myTask));
}
executorService.shutdown();
for(Future<String> future:futureList){
System.out.println(future.get());
}
}
}
class MyTask implements Callable<String> {
int i;
public MyTask(int i){
this.i = i;
}
@Override
public String call() throws Exception {
System.out.println("正在执行一个Task: 执行第 "+i+" 个 task.");
Thread.sleep(5000);
return "结果:" + i;
}
}
代码说明:
- 这里我们首先创建一个 ExecutorService 对象,它是一个 FixedThreadPool 类型的线程池,最大线程数为 2。
- 然后我们创建 MyTask 类,作为要执行的 10 个 Task,每个 Task 执行 5 秒。
- 我们把所有的 Task 放入到一个 ArrayList 中,然后使用 executorService 来管理它们。
- 使用 futureList 来存储所有 Task 的结果,最后将结果输出。
输出结果如下:
正在执行一个Task: 执行第 4 个 task.
正在执行一个Task: 执行第 5 个 task.
正在执行一个Task: 执行第 0 个 task.
正在执行一个Task: 执行第 1 个 task.
正在执行一个Task: 执行第 2 个 task.
正在执行一个Task: 执行第 3 个 task.
正在执行一个Task: 执行第 6 个 task.
正在执行一个Task: 执行第 7 个 task.
正在执行一个Task: 执行第 8 个 task.
正在执行一个Task: 执行第 9 个 task.
结果:0
结果:1
结果:2
结果:3
结果:4
结果:5
结果:6
结果:7
结果:8
结果:9
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:理解java多线程中ExecutorService使用 - Python技术站