Java进程池并发处理多个任务版权声明
原创版权声明:本文是博客作者的原创文章,全文如下。 CC 4.0 BY-SA 版权协议,转载请附上原始来源链接和本声明。
指向本文的链接: https://blog.csdn.net/micro_hz/article/details/73865016
Java在语言级别提供了多线程支持。线程池可以避免频繁创建和销毁线程的开销。因此,我们经常使用线程池来完成项目中的多线程任务。
Java提供了Executors 该框架提供了一些可以轻松实现多线程异步操作的基本组件,Executors提供了一系列静态工厂方法来获取不同的ExecutorService实现,ExecutorService扩展了Executors接口,Executors很简单:
public interface Executor {
void execute(Runnable command);
}
将任务本身与任务的执行分离,如果Runnable是一种可以异步执行任务的抽象,Executor它是对如何执行可以异步执行的任务的抽象。
这篇文章没有解释线程的一些基本知识,因为Internet上的其他文章已经写得足够详细和泛滥了。我编写了多个异步任务来解决并发执行和结果获取问题。假设我们想要组装一个对象,该对象由大量不相关和不依赖的小内容组成。如果我们连续执行,如果每项任务都需要时间10秒,总计10一项任务,那么我们需要100几秒钟就能得到结果。显然,我们可以使用线程池,每个任务一个线程,忽略线程开始时间,我们只需要10结果可以在几秒钟内得到。这里还有两个选择,这个10我们可以在几秒钟内做其他事情,也可以等待结果。
让我们这样做:
// 这是任务的抽象
class GetContentTask implements Callable {
private String name; private Integer sleepTimes; public GetContentTask(String name, Integer sleepTimes) { this.name = name; this.sleepTimes = sleepTimes; } public String call() throws Exception { // 假设这是一项耗时的操作。 Thread.sleep(sleepTimes * 1000); return "this is content : hello " + this.name; } }
采用completionService :
// 方法一
ExecutorService executorService = Executors.newCachedThreadPool();
CompletionService completionService = new ExecutorCompletionService(executorService);
ExecuteServiceDemo executeServiceDemo = new ExecuteServiceDemo();
// 十个
long startTime = System.currentTimeMillis();
int count = 0;
for (int i = 0;i < 10;i ++) {
count ++;
GetContentTask getContentTask = new ExecuteServiceDemo.GetContentTask("micro" + i, 10);
completionService.submit(getContentTask);
}
System.out.println("提交任务后,主线程处于空闲状态。, 可以做一些事情。");
// 假装做了8其他事情的秒数
try {
Thread.sleep(8000);
System.out.println("主线程已完成,正在等待结果。");
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
// 做好事情需要结果
for (int i = 0;i < count;i ++) {
Future result = completionService.take();
System.out.println(result.get());
}
long endTime = System.currentTimeMillis();
System.out.println("耗时 : " + (endTime - startTime) / 1000);
} catch (Exception ex) {
System.out.println(ex.getMessage());
}
执行结果为:
提交任务后,主线程处于空闲状态。, 可以做一些事情。
主线程已完成,正在等待结果。
this is content : hello micro9
this is content : hello micro7
this is content : hello micro2
this is content : hello micro5
this is content : hello micro4
this is content : hello micro8
this is content : hello micro1
this is content : hello micro3
this is content : hello micro0
this is content : hello micro6
耗时 : 10
如果多人不想逐一提交,您可以使用 invokeAll一起提交,但同时等待这些任务。
// 方法二
ExecutorService executeService = Executors.newCachedThreadPool();
List taskList = new ArrayList();
long startTime = System.currentTimeMillis();
for (int i = 0;i < 10;i ++) {
taskList.add(new GetContentTask("micro" + i, 10));
}
try {
System.out.println("主线程发起一个异步任务请求。");
List> resultList = executeService.invokeAll(taskList);
// 在这里将会有一个封闭式等候。resultList在获得所有异步执行的结果之前,它不会执行。
for (Future future : resultList) {
System.out.println(future.get());
}
// 主线程假装非常忙于执行8秒钟
Thread.sleep(8);
long endTime = System.currentTimeMillis();
System.out.println("耗时 : " + (endTime - startTime) / 1000);
} catch (Exception e) {
e.printStackTrace();
}
主线程发起一个异步任务请求。
this is content : hello micro0
this is content : hello micro1
this is content : hello micro2
this is content : hello micro3
this is content : hello micro4
this is content : hello micro5
this is content : hello micro6
this is content : hello micro7
this is content : hello micro8
this is content : hello micro9
耗时 : 10
如果有一系列的请求,我们不需要等待每个请求,我们可以。invokeAny,只要返回请求即可。
ExecutorService executorService = Executors.newCachedThreadPool();
ArrayList taskList = new ArrayList();
taskList.add(new GetContentTask("micro1",3));
taskList.add(new GetContentTask("micro2", 6));
try {
List> resultList = executorService.invokeAll(taskList);// 等待6秒
// String result2 = executorService.invokeAny(taskList); // 等待3秒
// invokeAll 提交一组任务进行并行处理,并得到结果。
// invokeAny就是提交一系列并行任务来获得结果
for (Future result : resultList) {
System.out.println(result.get());
}
// System.out.println(result2);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("主线程正在等待");
如果我发送了一堆异步任务,但我只等待了一段时间,如果我不在指定的时间返回它,我就不想要它。例如,网络多次请求其他服务器。如果他们想要数据,他们不能因为网络原因而一直等待。他们可以在规定的时间内拿到。如果他们无法获取,我将使用缺省值。对于这样的场景,我们可以使用以下文字:
try {
ExecutorService executorService = Executors.newCachedThreadPool();
List> taskList = new ArrayList>();
taskList.add(new GetContentTask("micro1", 4));
taskList.add(new GetContentTask("micro2", 6));
// 等待五秒
List> resultList = executorService.invokeAll(taskList, 5, TimeUnit.SECONDS);
for (Future future : resultList) {
System.out.println(future.get());
}
} catch (Exception e) {
e.printStackTrace();
}
this is content : hello micro1
java.util.concurrent.CancellationException
at java.util.concurrent.FutureTask.report(FutureTask.java:121)
at java.util.concurrent.FutureTask.get(FutureTask.java:192)
at com.micro.demo.spring.ExecuteServiceDemo.main(ExecuteServiceDemo.java:105)
因为只有等待5秒,6秒的任务不能自然获得,抛出异常。如果设置了等待时间8几秒钟,你就能得到。
版权声明
所有资源都来源于爬虫采集,如有侵权请联系我们,我们将立即删除