四种封装 ThreadPoolExecutor 的线程池的使用以及直接使用 ThreadPoolExecutor ,优缺点分析

池化思想:线程池、字符串常量池、数据库连接池
提高资源的利用率
下面是手动创建线程和执行任务过程,可见挺麻烦的,而且线程利用率不高。

  1. 手动创建线程对象
  2. 执行任务
  3. 执行完毕,释放线程对象

线程池的优点:

  • 提高线程的利用率
  • 提高程序的响应速度
  • 便于统一管理线程对象
  • 可以控制最大并发数
package chapter09;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.*;

public class Java05_Thread_Pool {
    public static void main(String[] args) {
        // TODO 线程 - 线程池
        // 所谓线程池,其实就是线程对象的容器
        // 可以根据需要,在启动时,创建一个或多个线程对象

        // 快速创建线程池的4种比较常见的方法
        // 它们都是对 ThreadPoolExecutor 的封装,那必然无法满足更复杂,更需要自定义功能的需求场景
        // 1. 创建固定数量的线程对象
        //    ExecutorService是线程服务对象
         ExecutorService executorService = Executors.newFixedThreadPool(3);
        // 2. 根据需求动态创建线程, 创建的线程可以重复使用,只是当目前线程不够了他会动态增加线程
        executorService = Executors.newCachedThreadPool();
        // 3. 单一线程
        executorService = Executors.newSingleThreadExecutor();
        // 4. 定时调度线程, 线程有3个,但是线程在什么时候执行我们可以去定义他
        executorService = Executors.newScheduledThreadPool(3);

        // 使用submit提交任务
        for (int i = 0; i < 5; i++) {
            executorService.submit(new Runnable() {
                @Override
                public void run() {
                    System.out.println("submit方式 " + Thread.currentThread().getName());
                }
            });
        }

        // 使用execute提交任务
        for (int i = 0; i < 5; i++) {
            executorService.execute(new Runnable() {
                @Override
                public void run() {
                    System.out.println("execute方式 " + Thread.currentThread().getName());
                }
            });
        }

        executorService.shutdown(); // 关闭线程池

         // 如果你需要更多的控制和自定义选项,使用 ThreadPoolExecutor 可以满足更复杂的需求
        // 使用银行柜台服务的场景来解释 ThreadPoolExecutor 的每个参数
        ExecutorService executorService1 = new ThreadPoolExecutor(
                3,  // corePoolSize-核心线程数,即银行的初始柜台数,
                // 具体来说:银行一开始有 3 个柜台,每个柜台有一个员工(线程)在处理客户(任务)。这些柜台是常驻的,即使没有客户时也不会关闭

                5,  // maximumPoolSize-最大线程数,即银行在高峰期能开设的最大柜台数量
                // 在客户数量增加的时候,银行可以最多开设 5 个柜台来处理客户。超过这个数量的客户需要排队等候

                1L, // keepAliveTime-非核心线程的存活时间
                // 如果一个临时增加的柜台(超过核心柜台数的部分)空闲了 1 秒钟,那么这个柜台就会关闭(线程会被回收)。
                // 这就像银行在高峰期增加了柜台,但在高峰期过后,临时柜台会在短时间内关闭,以节省资源

                TimeUnit.SECONDS, // keepAliveTime's unit-存活时间的单位
                // 这里的单位是秒,表示非核心线程在空闲 1 秒后会被关闭,跟上面的 keepAliveTime 配合使用


                new ArrayBlockingQueue<>(3), // workQueue-等待队列,用于存放等待处理的任务
                // 假如银行有一个容量为 3 的等候区(队列),当所有柜台都在忙碌时,新的客户会在这个等候区等待。
                // 如果等候区也满了,那么将会触发下面handler的策略(下面是 拒绝策略)

                Executors.defaultThreadFactory(), // threadFactory-线程工厂,用于创建新线程
                // 这是一个工厂模式,负责为银行创建新的柜台(线程)。
                // Executors.defaultThreadFactory() 是默认的实现,它会创建一个新的线程来处理任务。


                new ThreadPoolExecutor.AbortPolicy() // handler-当线程池和等待队列都满了时如何处理新任务的策略
                // 如果所有的柜台(线程)和等候区(队列)都满了,再来新的客户时会执行拒绝策略。
                // AbortPolicy 会抛出 RejectedExecutionException,就像银行告诉新来的客户“我们现在无法处理您的请求,请稍后再试”。
        );

        /*
        ExecutorService类对象可以使用两种方法向线程池提交任务:submit 和 execute。
        execute 方法用于提交不需要返回结果的任务。它是 Executor 接口中的方法
            返回类型: void。execute 方法不返回任何结果。
            异常处理: 如果任务在执行过程中抛出未经检查的异常,该异常将直接传播到调用者所在的线程。
            适用场景: 适用于不需要返回结果的任务,比如简单的异步执行任务。

        submit 方法用于提交有返回结果的任务。它是 ExecutorService 接口中的方法。
            返回类型: Future<V>。submit 方法返回一个 Future 对象,可以通过该对象获取任务的执行结果或取消任务。
            异常处理: 如果任务在执行过程中抛出未经检查的异常,该异常将被捕获,并存储在返回的 Future 对象中。调用 Future.get() 方法时,会抛出 ExecutionException。
            适用场景: 适用于需要返回结果的任务,比如计算任务,或者你需要检查任务是否成功完成。

        通过这两种方法,你可以根据任务的具体需求来选择合适的提交方式。
        如果任务需要返回结果或需要检查执行状态,使用 submit;
        如果任务只是执行,不需要返回结果,使用 execute。
         */

        List<Future<Integer>> futureList = new ArrayList<>();
        // 使用submit提交任务,并且改变需要执行的Runnable任务来看看线程池有什么变化情况
        // 任务数i在6个以内,executorService1指向的线程池只开3个线程
        // 7个任务开四个线程, 8个任务开五个线程
        // 9个任务直接 Exception in thread "main" java.util.concurrent.RejectedExecutionException
        // 解释:
        // 3个任务:直接全部给到三个核心线程处理
        // 4~6个任务:三个核心线程处理其中3个任务,剩下的任务进入等待队列
        // 7个任务:三个核心线程处理其中3个任务,等待队列存放3个任务,那还剩下1个任务就交给非核心线程处理(增设了一个额外的线程)
        // 8个任务:三个核心线程处理其中3个任务,等待队列存放3个任务,那还剩下2个任务就交给两个非核心线程处理(增设了两个额外的线程)
        // 9个任务:三个核心线程处理其中3个任务,等待队列存放3个任务,那还剩下3个任务,但是最大线程数是5个,
        // 也就是说再多只能在三个核心线程的基础上再增设两个额外的线程,但是也不够处理剩下的3个任务
        // 或者说 最大线程数大小 5 + 等待队列大小 3 = 8 < 任务所需的线程数 9
        for (int i = 1; i <= 3; i++) {
            int taskId = i;
            Future<Integer> future = executorService1.submit(new Callable() {
                @Override
                public Integer call() {
                    System.out.println(Thread.currentThread().getName() + "正在处理业务" + taskId);
                    return taskId;
                }
            });
            futureList.add(future);
        }

        Iterator<Future<Integer>> it = futureList.iterator();
        while (it.hasNext()) {
            Future<Integer> future = it.next();
            try {
                Integer result = future.get();
                System.out.println("Result: " + result);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            } catch (ExecutionException e) {
                throw new RuntimeException(e);
            }
        }

        // 使用execute方式提交任务
        for (int i = 1; i <= 9; i++) {
            int taskId = i;
            executorService1.execute(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName() + "正在处理业务" + taskId);
                }
            });
        }
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

揭秘数据之美:【Seaborn】在现代【数学建模】中的革命性应用

目录 已知数据集 tips 生成数据集并保存为CSV文件 数据预览&#xff1a; 导入和预览数据 步骤1&#xff1a;绘制散点图&#xff08;Scatter Plot&#xff09; 步骤2&#xff1a;添加回归线&#xff08;Regression Analysis&#xff09; 步骤3&#xff1a;分类变量分析&…

Mall,正在和年轻人重新对话

【潮汐商业评论/原创】 结束了一下午的苦闷培训&#xff0c;当Cindy赶到重庆十字大道时&#xff0c;才发现十字路口上的巨大“飞行棋”在前两天就已经撤展了。 “来了又错过&#xff0c;就会觉得遗憾&#xff0c;毕竟这样的路口不多&#xff0c;展陈又不可能会返场。” 飞行棋…

藏文作文写作业推荐什么学习工具?《藏文翻译词典》App值得你使用,一款好用准确的藏语词汇查询辞典!

探索藏语的奥秘&#xff0c;体验藏族文化的魅力&#xff0c;尽在《藏文翻译词典》App。这款App是藏汉翻译的神器&#xff0c;也是藏语学习者的必备工具。在学习过程中遇到不会的藏语单词&#xff0c;可以使用《藏文翻译词典》App进行查询&#xff01; 主要特性&#xff1a; 藏…

SCT612404通道,高效高集成,摄像头模组电源集成芯片

集成三路降压变换器&#xff0c;1CH高压BUCK,2CH低压Buck >HVBuck1:输入电压4.0V-20V,输出电流1.2A,Voo300mV/500mV >LVBuck2:输入电压2.7V-5V,输出电流0.6A , 固定1.8V输出 ;LVBuck3:输λ2.7V-5V,输出电流1.2A,可设定固定输出&#xff1a; 1 . 1 V / 1 . 2 V / 1 . 3 …

Intellj idea无法启动

个人电脑上安装的是2024.01版本的intellj idea作为开发工具&#xff0c;引入了javaagent作为工具包 但是在一次invaliad cache操作后&#xff0c;intellj idea就无法启动了&#xff0c;双击无响应。 重装了idea后也无效&#xff08;这个是有原因的&#xff0c;下面会讲&#…

开发人员使用的10大主流任务进度管理工具

本文将分享10大优质任务管理软件&#xff1a;Worktile、PingCode、Asana、Todoist、ClickUp、HubSpot Task Management、Hitask、Smartsheet、ProjectManager、Microsoft To Do。 任务管理软件不仅帮助个人和团队跟踪日常任务&#xff0c;还优化了工作流程&#xff0c;确保项目…

Linux/Ubuntu访问局域网共享文件夹

文件夹中找到“Other Location”&#xff0c;输入“smb:IP地址/共享文件夹名称”&#xff0c;然后点击connect后者直接回车即可&#xff01; End&#xff01;

Redis 主从,哨兵,cluster集群

概述 主从复制 主从复制是高可用Redis的基础&#xff0c;哨兵和集群都是在主从复制基础上实现高可用的。 主从复制主要实现了数据的多机备份&#xff0c;以及对于读操作的负载均衡和简单的故障恢复。 缺陷&#xff1a;故障恢复无法自动化&#xff1b;写操作无法负载均衡&am…

联合查询(多表查询)

多表查询是对多张表的数据取笛卡尔积&#xff08;关联查询可以对关联表使用别名&#xff09; 数据准备 insert into classes(name, desc) values (计算机系2019级1班, 学习了计算机原理、C和Java语言、数据结构和算法), (中文系2019级3班,学习了中国传统文学), (自动化2019级5…

Mysql 的第二次作业

一、数据库 1、登陆数据库 2、创建数据库zoo 3、修改数据库zoo字符集为gbk 4、选择当前数据库为zoo 5、查看创建数据库zoo信息 6、删除数据库zoo 1&#xff09;登陆数据库。 打开命令行&#xff0c;输入登陆用户名和密码。 mysql -uroot -p123456 ​ 2&#xff09;切换数据库…

前端修改audio背景色

1.查看浏览器设置Show user agent shadow DOM是否打开 2.打开可以查看audio Dom /** 去掉默认的背景颜色 */ audio::-webkit-media-controls-enclosure{background-color:unset; } 3.效果图

浅谈OpenCV的多对象匹配透明图像的实现,以及如何匹配半透明控件

引子 OpenCV提供的templateMatch只负责将&#xff08;相关性等&#xff09;计算出来&#xff0c;并不会直接提供目标的对应坐标&#xff0c;一般来说我们直接遍历最高的相关度&#xff0c;就可以得到匹配度最高的坐标。但是这样一般只能得到一个坐标。在实际操作中&#xff0c;…

边缘计算赋能:高效固体废物管理的ARMxy工业计算机实践

固体废物处理成为城市管理与环境保护的重要议题。传统处理方式效率低下且环境污染风险高&#xff0c;迫切需要智能化、高效化的解决方案。在此背景下&#xff0c;基于ARM架构的工业计算机以其低功耗、高性能及高度可定制性&#xff0c;正逐渐成为智能固体废物处理系统的核心驱动…

html三级菜单

示例 <!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8"> <meta name"viewport" content"widthdevice-width, initial-scale1.0"> <title>Menu Example</title> <link re…

工作效率飞跃提升

Hey小伙伴们&#x1f44b;&#xff0c;今天我要来给大家种草几款让我效率翻倍的超实用工具&#x1f6e0;️&#xff01;如果你也常常感觉时间不够用&#xff0c;这些小帮手绝对能让你事半功倍哦✨&#xff01; 1️⃣ 亿可达 — 软件连接器&#x1f517; 作为一款自动化工具&am…

SVN回退版本

我是直男, 所以, 就直接进入主题了 先本地备份要重新上传的代码文件 回退版本 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ → 然后提交刚刚回退的文件(别忘了) ← ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ 到这里…

【Python机器学习】处理文本数据——将文本数据表示为词袋

用于机器学习的文本有一种最简单的方法&#xff0c;也是最有效且最常用的方法&#xff0c;就是使用词袋表示。使用这种表示方法时&#xff0c;我们舍弃了输入文本中的大部分结构&#xff0c;比如章节、段落、句子和格式&#xff0c;只计算语料库中&#xff0c;只计算语料库中每…

Elasticsearch实战教程:如何使用集群索引数据来进行统计多个数据?

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 引入 Elasticsearch聚合查询是一种强大的工具&#xff0c;允许我们对索引中的数据进行复杂的统计分析和计算。本文将详细解释一…

为何整个 AI 领域都朝着 AI Agents 这一方向发展?

编者按&#xff1a; 当前大热的大语言模型和检索增强生成模型&#xff0c;虽然在语言理解和内容生成方面取得了突破性的进展&#xff0c;但仍然存在诸多限制。它们缺乏根据目标导引行为、持续学习和与环境交互的能力&#xff0c;难以应对复杂多变的现实场景需求。 今天为大家带…

国信华源全力守护湖南水库安全,汛期坚守岗位

连日来&#xff0c;湖南省遭受持续强降雨侵袭&#xff0c;部分地区暴雨倾盆&#xff0c;山塘河库水位急剧上升&#xff0c;防汛形势极为严峻。面对这场防汛大考&#xff0c;北京国信华源公司迅速响应&#xff0c;技术团队以高度的责任感和使命感&#xff0c;全力投入防汛减灾工…