四种线程池的使用,优缺点分析

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

  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/773805.html

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

相关文章

开发在线教育项目-在线课程视频网站开发

用了哪些技术 后端技术 springboot3 security权限框架&#xff08;后台&#xff09;mybatisPlus框架jwt生成tokeneasyexcel导入导出递归查询拦截器校验tokenredis的zset做排行榜功能redis的list做最新课程的功能redis做为缓存技术redis作为计数器&#xff0c;实时记录浏览量&…

极狐GitLab 将亮相2024空天信息大会暨数字地球生态峰会,携手中科星图赋能空天行业开发者

GitLab 是一个全球知名的一体化 DevOps 平台&#xff0c;很多人都通过私有化部署 GitLab 来进行源代码托管。极狐GitLab &#xff1a;https://gitlab.cn/install?channelcontent&utm_sourcecsdn 是 GitLab 在中国的发行版&#xff0c;专门为中国程序员服务。可以一键式部署…

【Proteus】按键的实现『⒉种』

&#x1f6a9; WRITE IN FRONT &#x1f6a9; &#x1f50e; 介绍&#xff1a;"謓泽"正在路上朝着"攻城狮"方向"前进四" &#x1f50e;&#x1f3c5; 荣誉&#xff1a;2021|2022年度博客之星物联网与嵌入式开发TOP5|TOP4、2021|2222年获评…

微信小程序毕业设计-走失人员的报备平台系统项目开发实战(附源码+论文)

大家好&#xff01;我是程序猿老A&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;微信小程序毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计…

【Python学习】流程控制、函数与类详解

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 引言 Python作为一门强大而又简洁的编程语言&#xff0c;提供了丰富的工具和结构来帮助开发者编写清晰、高效的代码。在本文中…

企业搭建知识库:解锁无限潜力的钥匙

在当今这个信息爆炸的时代&#xff0c;企业如何高效地管理、传播与利用知识&#xff0c;已成为衡量其竞争力的重要标尺。知识库&#xff0c;作为这一背景下的产物&#xff0c;正逐步成为企业不可或缺的数字资产。它不仅是一个自助式的数字门户&#xff0c;更是连接员工、客户与…

加入AIGC的小艺还有这些大用处 快来看

说到毕业&#xff0c;有不舍、有迷茫也有期待&#xff0c;在这种复杂的情绪里&#xff0c;手机里的小艺&#xff0c;简直是贴心小棉袄&#xff0c;给了我很多依靠&#xff0c;让我能勇敢的往前走。 在离别时候有太多的不舍&#xff0c;想要写段寄语记录下来&#xff0c;这时候小…

记录AllWinner H700芯片 LCD屏幕显示不正常,有色块问题

现象&#xff1a; 修改后&#xff1a; 文档&#xff1a; 测试命令&#xff08;需要kernel打开 CONFIG_DEVMEMy&#xff09;&#xff1a; 读取&#xff1a; devmem2 $((0x6511000 0x0088)) w 写入&#xff1a; devmem2 $((0x6511000 0x0088)) w 0x7000000 代码&#xff1…

程序员自由创业周记#37:程序员创业的几个方向

程序员自由创业周记#37&#xff1a;程序员创业的几个方向 报志愿 这几天亲戚一外甥报志愿&#xff0c;让我推荐&#xff0c;我基于自己的认知觉得还是计算机相关是第一优选&#xff0c;即便现在各大互联网公司都过得不怎么好&#xff0c;裁员的消息此起彼伏&#xff0c;很多计…

从零到一:eBay自养号测评全流程解析与实操建议

eBay自养号测评是一种通过模拟真实买家行为&#xff0c;为卖家提供市场反馈并提升店铺权重和排名的技术手段。以下是进行eBay自养号测评的具体步骤和注意事项&#xff1a; 一、准备阶段 1. 技术配置&#xff1a;搭建境外服务器&#xff1a;选择稳定的境外服务器&#xff0c;模…

内网学习第6天 liunx定时任务 环境变量和权限配置,以及数据库提权

内网学习的第5天呢&#xff1f;&#xff1f;我就没有写&#xff0c;那个主要就是利用内核漏洞以及suid&#xff0c;来进行提权的。 我在虚拟机上面进行提权&#xff0c;我没有成功&#xff0c;我本地的虚拟机呢&#xff0c;扫出来的漏洞poc也没有让我提权成功。所以我就没有写…

知识图谱构建助手安装配置使用!Sapphire Ventures最全Sales AI图谱:AI如何重塑销售行业?

知识图谱构建助手安装配置使用!Sapphire Ventures最全Sales AI图谱:AI如何重塑销售行业? 项目简介 llmgraph 使您能够从给定的源实体维基百科页面创建 GraphML、GEXF 和 HTML 格式(通过 pyvis 生成)的知识图。知识图谱是通过从 ChatGPT 或 LiteLLM 支持的其他大型语言模型…

从零开始开发跑腿配送系统:技术选型与架构设计

开发一个跑腿配送系统涉及多个技术栈和模块&#xff0c;从前端到后端&#xff0c;再到数据库和实时通信&#xff0c;每一个环节都至关重要。本文将详细介绍从零开始开发跑腿配送系统的技术选型与架构设计&#xff0c;并提供部分代码示例以帮助理解。 一、技术选型 前端技术&am…

视频号矩阵源码:构建短视频生态的基石

在数字化时代&#xff0c;视频内容已成为连接品牌与消费者的重要桥梁。视频号矩阵源码&#xff0c;作为短视频营销自动化的创新引擎&#xff0c;正在帮助内容创作者和营销团队以前所未有的效率和智能&#xff0c;管理和扩展他们的视频内容。本文将深入探讨视频号矩阵源码的核心…

13-错误-ERROR: duplicate key value violates unique constraint “ux_xxx“

13-错误-ERROR: duplicate key value violates unique constraint “ux_xxx” 更多内容欢迎关注我&#xff08;持续更新中&#xff0c;欢迎Star✨&#xff09; Github&#xff1a;CodeZeng1998/Java-Developer-Work-Note 技术公众号&#xff1a;CodeZeng1998&#xff08;纯纯…

代谢组数据分析(十二):岭回归、Lasso回归、弹性网络回归构建预测模型

欢迎大家关注全网生信学习者系列: WX公zhong号:生信学习者Xiao hong书:生信学习者知hu:生信学习者CDSN:生信学习者2介绍 在代谢物预测模型的构建中,我们采用了三种主流的回归分析方法:岭回归、Lasso回归以及弹性网络回归。这三种方法各有其独特的原理和适用场景,因此在…

从0构建一款appium-inspector工具

上一篇博客从源码层面解释了appium-inspector工具实现原理&#xff0c;这篇博客将介绍如何从0构建一款简单的类似appium-inspector的工具。如果要实现一款类似appium-inspector的demo工具&#xff0c;大致需要完成如下六个模块内容 启动 Appium 服务器连接到移动设备或模拟器启…

HTML+CSS笔记

标签 HTML标签 网页的大包围 整体网页内容的外衣 所有的网页文档内容都要写在 html标签内 lang属性&#xff0c;是指内容语言的&#xff0c;目的是让浏览器知晓这个页面的主要展示语言 是什么 只跟浏览器的翻译有关 主要展示的语言如果是英语 en&#xff0c;主要展示的语言如果…

移动硬盘传输中断后无法识别:深度解析与数据救援指南

在日常的数据存储与传输过程中&#xff0c;移动硬盘凭借其大容量、便携性成为众多用户的首选。然而&#xff0c;当我们在复制或移动大量数据时遭遇传输中断&#xff0c;随后发现移动硬盘无法被电脑识别&#xff0c;这无疑是一场数据安全的紧急警报。此情此景&#xff0c;不仅影…

Docker学习笔记(三)Dockerfile

一、什么是Dockerfile Dockerfile 是一个用于自动化构建 Docker 镜像的文本文件&#xff0c;其中包含了从一个基础镜像开始&#xff0c;到最终形成所需定制镜像的所有指令集。这个文件中的每一条指令都对应着构建镜像过程中的一个步骤或一层&#xff0c;指导 Docker 如何安装软…