JavaSE-线程池(5)- ThreadPoolExecutor常用方法

news2024/11/15 8:32:41

JavaSE-线程池(5)- ThreadPoolExecutor常用方法

invokeAll

ExecutorService 接口中定义的方法,给定一组任务,在所有任务执行完成时返回一个 Futures 列表,其中包含它们的状态和结果。

/**
 * Executes the given tasks, returning a list of Futures holding
 * their status and results when all complete.
 * {@link Future#isDone} is {@code true} for each
 * element of the returned list.
 * Note that a <em>completed</em> task could have
 * terminated either normally or by throwing an exception.
 * The results of this method are undefined if the given
 * collection is modified while this operation is in progress.
 *
 * @param tasks the collection of tasks
 * @param <T> the type of the values returned from the tasks
 * @return a list of Futures representing the tasks, in the same
 *         sequential order as produced by the iterator for the
 *         given task list, each of which has completed
 * @throws InterruptedException if interrupted while waiting, in
 *         which case unfinished tasks are cancelled
 * @throws NullPointerException if tasks or any of its elements are {@code null}
 * @throws RejectedExecutionException if any task cannot be
 *         scheduled for execution
 */
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
    throws InterruptedException;

invokeAll 使用方式

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class ThreadPoolExecutorInvokeAllTest {
    static class MyTask implements Callable<Boolean> {

        private int id;

        public MyTask(int id) {
            this.id = id;
        }

        @Override
        public Boolean call() throws Exception {
            try {
                System.out.println(
                    "time:" + System.currentTimeMillis() + " " + Thread.currentThread() + " execute task " + id +
                        " start");
                Thread.sleep(2000);
                System.out.println(
                    "time:" + System.currentTimeMillis() + " " + Thread.currentThread() + " execute task " + id +
                        " finish");
            } catch (InterruptedException e) {
                e.printStackTrace();
                return false;
            }
            return true;
        }
    }

    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        ThreadPoolExecutor executor =
            new ThreadPoolExecutor(10, 40, 5000,
                TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(2));
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());

        List<Callable<Boolean>> tasks = new ArrayList<>();
        for (int i = 1; i <= 5; i++) {
            tasks.add(new MyTask(i));
        }
        List<Future<Boolean>> futures = null;
        try {
            futures = executor.invokeAll(tasks);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("time:" + System.currentTimeMillis() + " 主线程会等待invokeAll执行完成才继续执行");
        for (int i = 0; i < futures.size(); i++) {
            try {
                System.out.println(futures.get(i).get());
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
        executor.shutdown();
        System.out.println("耗时:" + (System.currentTimeMillis() - start));
    }
}

如打印结果所示,主线程会等待 invokeAll 方法中的任务执行完后才继续执行

time:1677229181926 Thread[pool-1-thread-1,5,main] execute task 1 start
time:1677229181927 Thread[pool-1-thread-2,5,main] execute task 2 start
time:1677229181928 Thread[pool-1-thread-3,5,main] execute task 3 start
time:1677229181929 Thread[pool-1-thread-4,5,main] execute task 4 start
time:1677229181930 Thread[pool-1-thread-5,5,main] execute task 5 start
time:1677229183942 Thread[pool-1-thread-2,5,main] execute task 2 finish
time:1677229183942 Thread[pool-1-thread-1,5,main] execute task 1 finish
time:1677229183942 Thread[pool-1-thread-3,5,main] execute task 3 finish
time:1677229183942 Thread[pool-1-thread-5,5,main] execute task 5 finish
time:1677229183942 Thread[pool-1-thread-4,5,main] execute task 4 finish
time:1677229183965 主线程会等待invokeAll执行完成才继续执行
true
true
true
true
true
耗时:2141

一般在使用 invokeAll 方法时建议加上等待时间,防止任务执行时间过长线程一直阻塞,方法定义如下:

<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
                                  long timeout, TimeUnit unit)
        throws InterruptedException;

如果在 1 秒钟时间内任务没有结束将会被取消

futures = executor.invokeAll(tasks,1,TimeUnit.SECONDS);

执行结果如下:

time:1677231068880 Thread[pool-1-thread-1,5,main] execute task 1 start
time:1677231068881 Thread[pool-1-thread-3,5,main] execute task 3 start
time:1677231068880 Thread[pool-1-thread-2,5,main] execute task 2 start
time:1677231068881 Thread[pool-1-thread-4,5,main] execute task 4 start
time:1677231068881 Thread[pool-1-thread-5,5,main] execute task 5 start
java.lang.InterruptedException: sleep interrupted
	at java.lang.Thread.sleep(Native Method)
	at test.executors.ThreadPoolExecutorInvokeAllTest$MyTask.call(ThreadPoolExecutorInvokeAllTest.java:27)
	at test.executors.ThreadPoolExecutorInvokeAllTest$MyTask.call(ThreadPoolExecutorInvokeAllTest.java:13)
	at java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:266)
	at java.util.concurrent.FutureTask.run(FutureTask.java)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:750)
。。。省略部分报错
java.util.concurrent.CancellationException
	at java.util.concurrent.FutureTask.report(FutureTask.java:121)
	at java.util.concurrent.FutureTask.get(FutureTask.java:192)
	at test.executors.ThreadPoolExecutorInvokeAllTest.main(ThreadPoolExecutorInvokeAllTest.java:59)
java.util.concurrent.CancellationException
	at java.util.concurrent.FutureTask.report(FutureTask.java:121)
	at java.util.concurrent.FutureTask.get(FutureTask.java:192)
	at test.executors.ThreadPoolExecutorInvokeAllTest.main(ThreadPoolExecutorInvokeAllTest.java:59)
。。。省略部分报错
time:1677231069895 主线程会等待invokeAll执行完成才继续执行
耗时:1113

invokeAny

ExecutorService 接口中定义的方法,给定一组任务,只要有一个任务执行完成就返回这个任务的结果

/**
* Executes the given tasks, returning the result
* of one that has completed successfully (i.e., without throwing
* an exception), if any do. Upon normal or exceptional return,
* tasks that have not completed are cancelled.
* The results of this method are undefined if the given
* collection is modified while this operation is in progress.
* 执行给定的任务,返回成功完成的任务的结果(即没有抛出异常),如果有的话。
* 在正常或异常返回时,未完成的任务将被取消。如果在执行此操作时修改了给定的集合,则此方法的结果是未定义的。
*/
<T> T invokeAny(Collection<? extends Callable<T>> tasks)
   throws InterruptedException, ExecutionException;

invokeAny 使用方式

如下,有5个任务,每个任务等待时间为 0-3 秒,线程池调用 invokeAny 方法获取最终执行的任务名称

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class ThreadPoolExecutorInvokeAnyTest {
    static class MyTask implements Callable<String> {

        private int id;

        public MyTask(int id) {
            this.id = id;
        }

        @Override
        public String call() throws Exception {
            Integer randomTime = new Random().nextInt(4) * 1000;
            try {
                System.out.println(
                    "time:" + System.currentTimeMillis() + " " + Thread.currentThread() + " execute task " + id +
                        " start,random time :"+randomTime);
                Thread.sleep(randomTime);
                System.out.println(
                    "time:" + System.currentTimeMillis() + " " + Thread.currentThread() + " execute task " + id +
                        " finish");
            } catch (InterruptedException e) {
                e.printStackTrace();
                return "";
            }
            return "task" + id;
        }
    }

    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        ThreadPoolExecutor executor =
            new ThreadPoolExecutor(10, 40, 5000,
                TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(2));
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());

        List<Callable<String>> tasks = new ArrayList<>();
        for (int i = 1; i <= 5; i++) {
            tasks.add(new MyTask(i));
        }
        String futureResult = null;
        try {
            futureResult = executor.invokeAny(tasks, 3, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        } catch (TimeoutException e) {
            e.printStackTrace();
        }
        System.out.println("time:" + System.currentTimeMillis() + " 主线程会等待invokeAny执行完成才继续执行");
        System.out.println("执行的任务为:" + futureResult);
        executor.shutdown();
        System.out.println("耗时:" + (System.currentTimeMillis() - start));
    }
}

执行结果如下,task5等待0秒,所以 invokeAny方法返回结果为task5,其他任务等待时间都超过0秒,所以都被取消执行

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/376613.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java基础:常见API(Math,System,Runtime,Object,BigInteger,BigDecima)

1.常见API 1.1 Math类 向上取整是向着数轴右边走的意思, 负数也是. 也可以叫进一法, 不论正数负数都会往右走一. 向下取整是向着数轴左边走. 也可以叫去尾法, 不论正负数都会将小数点后的数字去掉. 1.1.2 练习 // 判断有多少水仙花数int count 0;for (int i 100; i < 1…

代码随想录算法训练营九期第十三天 | 239. 滑动窗口最大值、347.前 K 个高频元素、总结

打卡第十三天&#xff0c;昨天休息&#xff0c;今天继续栈和队列&#xff0c;重新复习了单调队列&#xff0c;上次看ACwing的视频学了单调队列&#xff0c;没有完全学明白&#xff0c;重学之后比之前清晰多了 今日任务 滑动窗口最大值 347.前 K 个高频元素总结 239. 滑动窗口最…

【Ap AutoSAR入门与实战开发02】-【Ap_s2s模块01】: s2s的背景

总目录链接==>> AutoSAR入门和实战系列总目录 文章目录 1 s2s的背景?2 AUTOSAR 方法应支持车辆的无缝开发2.1 面向服务的ECU的解读2.2 面向信号的ECU的解读2.3 通过网关ECU实现转换1 s2s的背景? Cp AutoSAR基于传统的can,lin,flexray总线的通信,一般是面向信号设…

汽车网络安全需求分析方法综述

引言&#xff1a; 近年来&#xff0c;汽车的网络安全问题逐渐被重视&#xff0c;在汽车产品的全生命周期中&#xff0c;需要进行网络安全风险管理&#xff0c;其主要活动包括网络安全需求分析、安全策略设计与实施、运营阶段安全监控与应急响应等。 安全需求分析工作作为系统安…

信息安全概论之《密码编码学与网络安全----原理与实践(第八版)》

前言&#xff1a;在信息安全概论课程的学习中&#xff0c;参考了《密码编码学与网络安全----原理与实践&#xff08;第八版&#xff09;》一书。以下内容为以课件为主要参考&#xff0c;课本内容与网络资源为辅助参考&#xff0c;学习该课程后作出的总结。 一、信息安全概述 1…

【蓝桥杯集训9】单调栈、单调队列(模拟栈、模拟队列)专题(3 / 3)

目录 单调栈模板 1、模拟栈 单调队列模板 1、模拟队列 2、双端队列 135. 最大子序和 - 前缀和滑动窗口单调队列 单调栈模板 什么时候用单调栈&#xff1f; 求序列中每一个数左边或右边第一个比它大或小的数 1、单调递增栈 在保持栈内元素单调递增前提下&#xff08;如果…

Redis 主从库如何实现数据一致?

目录 1、主从库间如何进行第一次同步&#xff1f; 2、主从级联模式分担全量复制时的主库压力 3、主从库间网络断了怎么办&#xff1f; 总结 // 好的文章&#xff0c;值得反复去读 Redis 具有高可靠性&#xff0c;这里有两层含义&#xff1a;一是数据尽量少丢失&#xff0c;…

2023JAVA面试题全集超全面超系统超实用!早做准备早上岸

2022年我凭借一份《Java面试核心知识点》成功拿下了阿里、字节、小米等大厂的offer&#xff0c;两年的时间&#xff0c;为了完成我给自己立的flag&#xff08;拿下一线互联网企业offer大满贯&#xff09;&#xff0c;即使在职也一直在不断的学习与备战面试中&#xff01;——或…

【Spark分布式内存计算框架——Spark Streaming】6. DStream(下)流式应用状态 Kafka

3.3 流式应用状态 使用SparkStreaming处理实际实时应用业务时&#xff0c;针对不同业务需求&#xff0c;需要使用不同的函数。SparkStreaming流式计算框架&#xff0c;针对具体业务主要分为三类&#xff0c;使用不同函数进行处理&#xff1a; 业务一&#xff1a;无状态Statel…

【数电基础】——数制和码制

目录 1.概述 1.信号&#xff08;电路&#xff09;的功能 2.信号的分类&#xff1a; 3.数字信号的输入和输出的逻辑关系表示方法 2.数制 1.十进制&#xff08;D/d&#xff09; 2.二进制(B/b) 3.八进制&#xff08;O/o&#xff09; 4.十六进制&#xff08;H/h&#xff09;…

使用huggingface微调预训练模型

官方教程&#xff1a;https://huggingface.co/docs/transformers/training 准备数据集&#xff08;基于datasets库&#xff09; train.json 数据格式&#xff1a; {"source":"你是谁&#xff1f;", "target":"我是恁爹"} {"so…

FSP:Flow of Solution Procedure (CVPR 2017) 原理与代码解析

paper&#xff1a;A Gift From Knowledge Distillation: Fast Optimization, Network Minimization and Transfer Learningcode&#xff1a;https://github.com/HobbitLong/RepDistiller/blob/master/distiller_zoo/FSP.py背景深度神经网络DNN逐层生成特征。更高层的特征更接近…

内存数据库的设计与实现(已在大型项目中应用)

一、概况 1、设计总图 组成,由Redis集群缓存,普通缓存,传统数据库,各类数据驱动 2、内存数据库的增删改查,分页查询 组成,由数据查询,分页查询,数据存储,数据修改,数据删除 3、内存数据库的驱动 组成,由驱动适配器,普通缓存驱动,Redis缓存驱动 4、内存数据库与…

C++常见类型及占用内存表

GPS生产厂家在定义数据的时候都会有一定的数据类型&#xff0c;例如double、int、float等&#xff0c;我们知道它们在内存中都对应了一定的字节大小&#xff0c;而我在实际使用时涉及到了端序的问题&#xff08;大端序高字节在前&#xff0c;小端序低字节在前&#xff09;&…

redis主从同步:如何实现数据一致

Redis 提供了主从库模式&#xff0c;以保证数据副本的一致&#xff0c;主从库之间采用的是读写分离的方式。读操作&#xff1a;主库、从库都可以接收&#xff1b;写操作&#xff1a;首先到主库执行&#xff0c;然后&#xff0c;主库将写操作同步给从库。和mysql差不多。但是同步…

自动驾驶专题介绍 ———— 毫米波雷达

文章目录介绍工作原理特点性能参数应用厂家介绍 毫米波雷达是工作在毫米波波段探测的雷达&#xff0c;与普通雷达相似&#xff0c;是通过发射无线电信号并接收反射信号来测量物体间的距离。毫米波雷达工作频率为30~300GHz(波长为1 - 10mm)&#xff0c;波长介于厘米波和光波之间…

【数据挖掘实战】——家用电器用户行为分析及事件识别(BP神经网络)

项目地址&#xff1a;Datamining_project: 数据挖掘实战项目代码 目录 一、背景和挖掘目标 1、问题背景 2、原始数据 3、挖掘目标 二、分析方法与过程 1、初步分析 2、总体流程 第一步&#xff1a;数据抽取 第二步&#xff1a;探索分析 第三步&#xff1a;数据的预处…

为什么负责任的技术始于数据治理

每个组织都处理数据&#xff0c;但并非每个组织都将其数据用作业务资产。但是&#xff0c;随着数据继续呈指数级增长&#xff0c;将数据视为业务资产正在成为竞争优势。 埃森哲的一项研究发现&#xff0c;只有 33% 的公司“足够信任他们的数据&#xff0c;能够有效地使用它并从…

色环电阻的阻值如何识别

这种是色环电阻&#xff0c;其外表有一圈圈不同颜色的色环&#xff0c;现在在一些电器和电源电路中还有使用。下面的两种色环电阻它颜色还不一样&#xff0c;一个蓝色&#xff0c;一个土黄色&#xff0c;其实这个蓝色的属于金属膜色环电阻&#xff0c;外表涂的是一层金属膜&…

Qt新手入门指南 - 如何创建模型/视图(四)

每个UI开发人员都应该了解ModelView编程&#xff0c;本教程的目标是为大家提供一个简单易懂的介绍。Qt 是目前最先进、最完整的跨平台C开发工具。它不仅完全实现了一次编写&#xff0c;所有平台无差别运行&#xff0c;更提供了几乎所有开发过程中需要用到的工具。如今&#xff…