Java进程池并发处理多个任务版权声明

原创
小哥 3年前 (2022-10-27) 阅读数 188 #CSS教程
文章标签 CSS

版权声明:本文是博客作者的原创文章,全文如下。 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几秒钟,你就能得到。

你觉得读了这篇文章后收获很大吗?

                                
版权声明

所有资源都来源于爬虫采集,如有侵权请联系我们,我们将立即删除

上一篇:RabbitMQ选择页面各种技能详解版权声明 下一篇:SimpleMappingExceptionResolver统一管理异常
热门
最新文章
标签列表