JavaEE多线程-线程池

目录

  • 线程池
  • Java标准库提供的线程池
  • 线程池的实现

线程池

线程池和和字符串常量池, 数据库连接池一样, 都是为了提高程序的运行效率, 减少开销。
随着并发程度的提高, 当我们去频繁的创建和销毁线程, 此时程序的开销还是挺大的, 为了进一步提高效率, 就引入了线程池, 程序中所创建的线程都会加载到一个 “池子” 中, 当程序需要使用线程的时候, 可以直接从池里面获取, 用完了就将线程还给池, 这样在多线程的环境中就不用去重复的创建和销毁线程, 从而使程序的运行效率提高, 线程池是管理线程的方式之一.

为什么从线程池中“拿”线程比直接创建线程更加高效?

1.第一点,线程池可以解决线程生命周期的系统开销问题,同时还可以加快响应速度。因为线程池中的线程是可以复用的,我们只用少量的线程去执行大量的任务,这就大大减小了线程生命周期的开销。而且线程通常不是等接到任务后再临时创建,而是已经创建好时刻准备执行任务,这样就消除了线程创建所带来的延迟,提升了响应速度,增强了用户体验。
2.第二点,线程池可以统筹内存和 CPU 的使用,避免资源使用不当。线程池会根据配置和任务数量灵活地控制线程数量,不够的时候就创建,太多的时候就回收,避免线程过多导致内存溢出,或线程太少导致 CPU 资源浪费,达到了一个完美的平衡。
3.第三点,线程池可以统一管理资源。比如线程池可以统一管理任务队列和线程,可以统一开始或结束任务,比单个线程逐一处理任务要更方便、更易于管理,同时也有利于数据统计,比如我们可以很方便地统计出已经执行过的任务的数量。

Java标准库提供的线程池

Java中提供了线程池相关的标准类ThreadPoolExecutor, 也被称作多线程执行器, 该类中的线程包括两类, 一类是核心线程, 另一类是非核心线程, 当核心线程都被占用还不能满足程序任务执行的需求时, 就会启用非核心线程, 直到任务量少了, 随之非核心线程也就会销毁.

jdk8中提供了4个构造方法, 这里主要介绍和理解参数最多的那一个构造方法, 其他构造方法只是基于这里的减少了参数而已.

public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          ThreadFactory threadFactory,
                          RejectedExecutionHandler handler)

  1. corePoolSize表示核心线程数
  2. maximumPoolSize表示最大线程数,就是核心线程数与非核心线程数之和
  3. keepAliveTime非核心线程最长等待新任务的时间, 超过此时间, 该线程就会被销毁
  4. unit上面参数的时间单位.
  5. workQueue线程池的任务队列(阻塞队列), 通过submit方法将任务注册到该队列中
  6. threadFactory线程工厂, 线程创建的方案.
  7. handler拒绝策略, 描述了当线程池任务队列满了, 如果继续添加任务会以什么样的方式处理.
  • 使用 Executors.newFixedThreadPool(10) 能创建出固定包含 10 个线程的线程池.
  • 返回值类型为 ExecutorService
  • 通过 ExecutorService.submit 可以注册一个任务到线程池中.
  • 在这里插入图片描述

    下面的是其他的几个构造方法:

    public ThreadPoolExecutor(int corePoolSize,
                                  int maximumPoolSize,
                                  long keepAliveTime,
                                  TimeUnit unit,
                                  BlockingQueue<Runnable> workQueue)
    
    public ThreadPoolExecutor(int corePoolSize,
                                  int maximumPoolSize,
                                  long keepAliveTime,
                                  TimeUnit unit,
                                  BlockingQueue<Runnable> workQueue,
                                  ThreadFactory threadFactory) 
    
    public ThreadPoolExecutor(int corePoolSize,
                                  int maximumPoolSize,
                                  long keepAliveTime,
                                  TimeUnit unit,
                                  BlockingQueue<Runnable> workQueue,
                                  RejectedExecutionHandler handler)
    
    

    使用线程池时, 往往使用的是ExecutorServerce,ExecutorServerceThreadPoolExecutor所实现的一个接口, 其中最重要的一个方法是submit方法, 这个方法能够将任务交给线程池去执行.

    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    //线程池
    //一般认为,纯用户态的操作,效率要比经过内核态处理的操作,要效果更高~~
    //线程池里面有什么?
    //1.先能够描述任务(直接用Runnable) 2.需要组织任务(直接用BlockingQueue) 3.能够描述工作线程  4.还需要组织这些线程 5.需要实现往线程池里添加任务
    public class Demo {
        public static void main(String[] args) {
            //创建一个固定线程数目的线程池,参数指定了线程个数
            ExecutorService pool = Executors.newFixedThreadPool(10);
            //创建一个自动扩容的线程池,会根据任务量来自动进行扩容
            //Executors.newCachedThreadPool();
            //创建一个只有一个线程的线程池
            //Executors.newSingleThreadExecutor();
            //创建一个带有定时器使用的线程池,类似于 Timer
            //Executors.newScheduledThreadPool();
    
            for (int i = 0; i < 100; i++) {
                pool.submit(new Runnable() {
                    @Override
                    public void run() {
                        System.out.println("Hello threadpool");
                    }
                });
            }
        }
    }
    
    

    Executors 创建线程池的几种方式

  • newFixedThreadPool: 创建固定线程数的线程池
  • newCachedThreadPool: 创建线程数目动态增长的线程池.
  • newSingleThreadExecutor: 创建只包含单个线程的线程池.
  • newScheduledThreadPool: 设定 延迟时间后执行命令,或者定期执行命令. 是进阶版的 Timer.
  • 线程池的实现

  • 任务, 可以直接使用`Runnable`实现.
  • 组织任务的数据结构, 使用阻塞队列`BlockingQueue`即可.
  • 若干个工作线程, 工作线程要通过一个循环不断的从阻塞队列中获取任务.
  • 注册任务的方法`submit,` 将任务添加到阻塞队列当中.
  • import java.util.concurrent.BlockingQueue;
    import java.util.concurrent.LinkedBlockingQueue;
    
    class MyThreadPool {
        //使用阻塞队列来保存任务
        private BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>();
    
        //这里创建出若干个工作线程,n表示线程的数量
        public MyThreadPool(int n) {
            for (int i = 0; i < n; i++) {
                Thread t = new Thread(() -> {
                    while (!Thread.interrupted()) {
                        try {
                            Runnable runnable = queue.take();
                            runnable.run();
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                    }
                });
                t.start();
            }
        }
    
        //注册任务给线程池
        public void submit(Runnable runnable) {
            try {
                queue.put(runnable);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
    
    

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

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

相关文章

基于Java+SSM+Vue的旅游资源网站设计与实现【源码(完整源码请私聊)+论文+演示视频+包运行成功】

博主介绍&#xff1a;专注于Java技术领域和毕业项目实战 &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;&#x1f3fb; 不然下次找不到哟 Java项目精品实战案例&#xff08;200套&#xff09; 目录 一、效果演示 二、…

Java语言-----封装、继承、抽象、多态、接口

目录 前言 一.封装 1.1封装的定义 1.2访问修饰符的使用 二.继承 2.1继承的定义 2.2继承的方法 2.3继承使用注意点 三.多态 3,1多态的定义 3.2动态绑定 3.3方法重写 3.4向上&#xff08;向下&#xff09;转型 四.抽象 4.1抽象的概述和定义 4.2抽象的使用 五…

python例程:AI智能联系人管理的程序

目录《AI智能联系人管理》程序使用说明主要代码演示代码工程下载路径《AI智能联系人管理》程序使用说明 在PyCharm中运行《AI智能联系人管理》即可进入如图1所示的系统主界面。 图1 系统主界面 说明&#xff1a;在运行程序前&#xff0c;先将当前的计算机连接互联网&#xff…

【网络】https协议

&#x1f941;作者&#xff1a; 华丞臧. &#x1f4d5;​​​​专栏&#xff1a;【网络】 各位读者老爷如果觉得博主写的不错&#xff0c;请诸位多多支持(点赞收藏关注)。如果有错误的地方&#xff0c;欢迎在评论区指出。 推荐一款刷题网站 &#x1f449; LeetCode刷题网站 文章…

【深度学习】常见的梯度下降的方法

批量梯度下降&#xff08;Batch Gradient Descent&#xff0c;BGD&#xff09; 这个方法是当所有的数据都经过了计算之后再整体除以它&#xff0c;即把所有样本的误差做平均。这里我想提醒你&#xff0c;在实际的开发中&#xff0c;往往有百万甚至千万数量级的样本&#xff0c…

python基于django的校园拼车系统

开发语言&#xff1a;Python 框架&#xff1a;django Python版本&#xff1a;python3 数据库&#xff1a;mysql 数据库工具&#xff1a;Navicat 登录注册模块 1.管理员登录 2.普通用户注册登录&#xff0c;注册时要求密码必须用数字、字母、特殊字符起码两种&#xff0c;并且…

Python每日一练(20230327)

目录 1. 最大矩形 &#x1f31f;&#x1f31f;&#x1f31f; 2. 反转链表 II &#x1f31f;&#x1f31f; 3. 单词接龙 II &#x1f31f;&#x1f31f;&#x1f31f; &#x1f31f; 每日一练刷题专栏 &#x1f31f; Golang每日一练 专栏 Python每日一练 专栏 C/C每日…

C生万物 | 校招热门考点 —— 结构体内存对齐

文章目录一、前言结构体偏移量计算&#xff1a;offsetof二、规则介绍例题的分解与细说三、习题演练1、练习①2、练习②四、为什么存在内存对齐?1、平台原因(移植原因)2、性能原因五、如何修改默认对齐数六、实战演练✍一道百度笔试题&#xff1a; offsetof 宏的实现&#x1f4…

自己设计的网站,如何实现分页功能?(详细代码+注释)

目录 前言 实现分页功能 需求分析 客户端开发 服务器开发 前后端交互——两种前端得到 文章总页数 的方法&#xff0c;那种更合适&#xff1f; 前言 你在设计网站的时候是否有过这样的烦恼&#xff1a;“我设计的网站怎么就是从上到下一条线内容全部展开&#xff0c;一点都…

IDEA 热部署,修改代码不用重启项目

热部署指在修改项目代码的时候不重启服务器让修改生效。安装JRebel and XRebelFile->Settings&#xff0c;然后Plugins-> Marketplace&#xff0c;输入JRebel&#xff0c;安装如下插件——JRebel and XRebel &#xff0c;重启idea激活JRebel and XRebel第一行输入网址&am…

linux入门---环境变量

目录标题指令的本质如何不加./方法一方法二环境变量的重置在命令行上查看环境变量为什么会存在环境变量在程序中查看环境变量本地变量和环境变量环境变量的继承指令的本质 在使用linux的时候我们经常会使用很多指令比如说&#xff1a;ll指令&#xff0c;pwd指令&#xff0c;wh…

Java JDK详细安装配置(详细备忘版本)

目录概览一、下载安装二、环境配置三、常见问题一、下载安装 官方下载地址&#xff1a;点我去官网 java20 、java17如下&#xff1a; java8、java11如下 jre8 如下 以 java8 下载为例&#xff1a; 按步骤输入账号密码 之后就会跳出下载显示框 得到了文件名为 jdk-8u361-win…

单机分布式一体化是什么?真的是数据库的未来吗,OceanBase或将开启新的里程碑

一. 数据 我们先说说数据这个东西&#xff0c;这段时间的ChatGPT在全世界的爆火说明了一件事&#xff0c;数据是有用的&#xff0c;并且大量的数据如果有一个合适的LLM大规模语言模型训练之后&#xff0c;可以很高程度的完成很多意想不到的事情。 我们大多数的时候的注意力只…

class03:MVVM模型与响应式原理

目录一、MVVM模型二、内在1. 深入响应式原理2. Object.entries3. 底层搭建一、MVVM模型 MVVM&#xff0c;即Model 、View、ViewModel。 Model > data数据 view > 视图&#xff08;vue模板&#xff09; ViewModel > vm > vue 返回的实例 > 控制中心, 负责监听…

ChatGPT使用介绍、ChatGPT+编程、相关组件和插件记录

文章目录介绍认识ChatGPT是通过英汉互译来实现中文回答的吗同一个问题&#xff0c;为什么中英文回答不同ChatGPT的使用对话组OpenAI APIAI智能绘图DALLE 2ChatGPT for Google插件ChatGPT编程编写代码代码错误修正与功能解读代码评审与优化推荐技术方案编写和优化SQL语句在代码编…

Spring Boot集成RocketMQ实现普通、延时、事务消息发送接收、PULL消费模式及开启ACL | Spring Cloud 30

一、前言 在前面我们通过以下章节对RocketMQ有了基础的了解&#xff1a; docker-compose 搭建RocketMQ 5.1.0 集群&#xff08;双主双从模式&#xff09; | Spring Cloud 28 docker-compose 搭建RocketMQ 5.1.0 集群开启ACL权限控制 | Spring Cloud 29 现在开始我们正式学习…

蓝桥杯 - 求组合数【C(a,b)】+ 卡特兰数

文章目录&#x1f4ac;前言885. 求组合数 I C(m,n) 【dp】886 求组合数 II 【数据大小10万级别】 【费马小定理快速幂逆元】887. 求组合数 III 【le18级别】 【卢卡斯定理 逆元 快速幂 】888.求组合数 IV 【没有%p -- 高精度算出准确结果】 【分解质因数 高精度乘法 --只用一…

5.5G产业再提速!高通5GAdvanced-ready芯片商用终端下半年面世

MWC2023大会召开在即&#xff0c;5GAdvanced产业再添重磅消息&#xff01;2月15日&#xff0c;高通宣布推出全球首个5GAdvanced-ready基带芯片——骁龙X755G调制解调器及射频系统&#xff0c;支持毫米波和Sub-6GHz频段&#xff0c;带来网络覆盖、时延、能效和移动性等全方位的提…

【C语言】深度理解指针(下)

一. 前言&#x1f48e;昨晚整理博客时突然发现指针还少了一篇没写&#xff0c;今天就顺便来补一补。上回书说到&#xff0c;emmm忘记了&#xff0c;没事&#xff0c;我们直接进入本期的内容:本期我们带来了几道指针相关笔试题的解析&#xff0c;还算是相对比较轻松的。话不多说…

RTL8201 以太网PHY芯片 调试记录

一、概述 为了尽量给甲方降低成本&#xff0c;决定使用较低成本的PHY芯片RTL8201F-VB-CG芯片。移植官网的以太网demo程序&#xff0c;git上下载了一份很好看的rtl8201F的驱动程序&#xff0c;用来替换官方demo的lan8742程序。并没有直接通&#xff0c;于是开始了调试之路。 二…