Java并发编程学习(五):批量并行执行任务的两种方式

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

Java并发编程学习(五):批量并⾏执⾏任务的两种⽅式
背景介绍
有时候我们需要执⾏⼀批相似的任务,并且要求这些任务能够并⾏执⾏。

通常,我们的需求会分为两种情况:
1. 并⾏执⾏⼀批任务,等待耗时最长的任务完成之后,再处理所有任务的结果。

2. 并⾏执⾏⼀批任务,依次处理完成的任务结果(哪个任务先执⾏完就先处理哪个)。

这篇⽂章要介绍的两种批量执⾏任务的⽅式,正好对应了上述两种情况,下⾯分别介绍在Java中,如何使⽤并发包⾥⾯的API完成我们的需求。

使⽤ExecutorSevice#invokeAll()
通过向线程池提交⼀组任务,可以实现上述第⼀种批量执⾏的需求。

下⾯来看具体例⼦。

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
public class Main {
public static void main(String[] args) throws InterruptedException, ExecutionException {
// 创建两个任务
Callable<Integer> task1 = () -> {
TimeUnit.SECONDS.sleep(3);
System.out.println("[" + Thread.currentThread().getName() + "]" + " task1 finished");
return 1;
};
Callable<Integer> task2 = () -> {
TimeUnit.SECONDS.sleep(10);
System.out.println("[" + Thread.currentThread().getName() + "]" + " task2 finished");
return 2;
};
List<Callable<Integer>> tasks = new ArrayList<>();
tasks.add(task1);
tasks.add(task2);
// 创建线程池
ExecutorService service = Executors.newFixedThreadPool(2);
// 调⽤invokeAll⽅法,批量提交⼀组任务
List<Future<Integer>> futures = service.invokeAll(tasks);
for (Future<Integer> future : futures) {
// 在这⾥获取任务的返回值时,会等待所有任务都执⾏完才返回结果
Integer result = future.get();
System.out.println("[" + Thread.currentThread().getName() + "]" + " " + result);
}
// 关闭线程池
service.shutdown();
}
}
执⾏结果:
使⽤CompletionService
CompletionService也可以⽤来提交⼀组任务,让这些任务并⾏执⾏,任何⼀个任务执⾏完之后别的线程可以⽴即获得计算结果。

看⼀下具体例⼦:
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
public class Main {
public static void main(String[] args) throws InterruptedException, ExecutionException {
// 创建两个任务
Callable<Integer> task1 = () -> {
TimeUnit.SECONDS.sleep(3);
System.out.println("[" + Thread.currentThread().getName() + "]" + " task1 finished");
return 1;
};
Callable<Integer> task2 = () -> {
try {
TimeUnit.SECONDS.sleep(10);
System.out.println("[" + Thread.currentThread().getName() + "]" + " task2 finished");
}catch (InterruptedException e) {
// 第⼆个任务耗时长,等第⼀个任务完成之后,⼿动取消第⼆个任务的执⾏,此时第⼆个任务可能会收到中断。

e.printStackTrace();
}
return 2;
};
List<Callable<Integer>> tasks = new ArrayList<>();
tasks.add(task1);
tasks.add(task2);
// 创建线程池
ExecutorService pool = Executors.newFixedThreadPool(2);
// 使⽤CompletionService批量提交任务
CompletionService<Integer> cs = new ExecutorCompletionService<>(pool);
List<Future<Integer>> futures = new ArrayList<>();
for (Callable<Integer> task : tasks) {
Future<Integer> f = cs.submit(task);
futures.add(f);
}
// 获取第⼀个执⾏完的任务结果
Future<Integer> f = cs.take();
System.out.println("[" + Thread.currentThread().getName() + "]" + f.get());
futures.remove(f);
// 取消其他任务
for (Future<Integer> future : futures) {
future.cancel(true);
}
// 关闭线程池
pool.shutdown();
}
}
运⾏结果:
第⼀个任务执⾏完之后,第⼆个任务还在运⾏中,但是我们已经不关⼼其计算结果了,⼿动取消这个任务的执⾏,因此第⼆个任务会收到⼀个中断。

相关文档
最新文档