[多线程]线程池

目录

1.前言

2. Java中的线程池以及参数介绍

2.1 核心线程数和最大线程数

2.2最大空闲存活时间

2.3任务队列和线程工厂

2.4 拒绝策略(最重要)

2.5 线程池的类型

3.线程池的大小如何确定

4.手动写一个线程池


1.前言

    我们知道.在开发过程中.为了效率,会引进很多池,比如常量池,对象池,字符串池.今天我们来介绍另一种可以管理线程的池,线程池.我们知道在多线程编程中,线程的开销是比较大的,如线程的摧毁和创建.为了解决这种问题,我们引入了线程池这个概念,它可以把部分线程的创建和销毁给省去了,而是直接放到特定的数据结构里,需要用的时候再拿出来.这样就可以极大的提升程序的效率

2. Java中的线程池以及参数介绍

  在Java中,也为我们封装了线程池的类,ThreadpollExecutor类,而这个类里面有几个重要的参数。它的构造方法有四种。             

    我们这里来重点介绍一下第四个构造方法,因为这个构造方法里的参数是最完整的。它包含了前面几个构造方法里的参数。

2.1 核心线程数和最大线程数

int  corePoolSize  核心线程数,相当于是正式的线程,正式工。

int maxmumPoolSize 最大线程数,除了核心线程,还有临时线程,相当于临时工,实习生。

2.2最大空闲存活时间

long keepAliveTime 实习生线程允许的最大空闲存活时间。 就是除了核心线程数之外的线程,在没有被利用到的时候,可以存在的时间。

TimeUnit unit 最大空闲存活时间单位,(s,hour,day。。。)

2.3任务队列和线程工厂

BlockkingQueue<Runable> workQueue 线程池里的任务队列,它是一个阻塞队列。

Threadfactry threadFactory 线程工厂

工厂模式可以解决Java语法的缺陷,就是在重载的时候,参数不能相同,但实际上,我们会有这种业务需求。比如,我们需要通过构造方法,来创建类,但是我们想传入的形参它的意义不同,但是类型和个数都一样。在Java基本语法中,是做不到的。但是我们可以通过把构造方法进行封装, 把它们放到工厂类里面去,通过工厂类来进行创建对象。

2.4 拒绝策略(最重要)

RejectedExecutionHandler  handler

  线程池中,会有一个阻塞队列。所以它能容纳的线程数量是有限的,当任务队列里的线程数满了以后,线程池会做出什么样的举动。这个是可以我们来控制一下的,所以就引入了 我们的拒绝策略。

在标准库里,Java为我们提供了四种拒绝策略。

我们来逐个解释一下这些拒绝策略分别是什么:
 

ThreadPoolExecutor.AbortPolicy  

   抛出一个 RejectedExecutionException ,举个例子,就好比我现在在家做家务,手头有好几个活,我妈这时候让我在做一个新的家务,如果是这种拒绝策略。那就是我情绪崩溃了,哇的一声就哭出来了,然后撂挑子不干了。

ThreadPoolExecutor.CallerRunsPolicy  

新的任务,由添加任务的线程去执行。也就是我上述例子中,我给我妈说,我不干,你去做。

ThreadPoolExecutor.DiscardOldestPolicy 
被拒绝的任务的处理程序,丢弃最旧的未处理请求。就是把队列中,最老的那个线程给丢掉,然后加入这个最新的。就是上述例子中,我有一个最早的家务,比如是拖地,我就不去做这个了,而是把新家务给放到我的家务计划中。

ThreadPoolExecutor.DiscardPolicy 

直接丢掉最新的,不要别的线程加入,加不进去。就是我直接拒绝了给我安排的家务,并不会出现在我的家务计划列表中。

2.5 线程池的类型

Java标准库中,有这么四类线程池的类型。我们来通过图片来给大家看看。

   如果只是简单用一下,就用这几种就可以了。如果需要高度定制化,那么就需ThreadPoolExecutor。来逐个设置参数了。阿里巴巴编程规范,要我们使用ThreadPoolExecutor。来让线程池更可控。可以参考一下。大家要以实际开发入职的编程规范为准。

3.线程池的大小如何确定

   网上有很多种关于线程池大小如何设定的说法,有的说如果cpu逻辑核心数是N,那么就应该设置为N个,1.5N.2N...但是这些说法都不严谨。

我们要看具体的代码里,线程中是cpu密集型的操作,还是io密集型的操作。如果是cpu密集型的操作,那么就设置为N就行,如果是io密集型的操作,这个时候对于cpu的消耗就比较小,我们就可以设置为远大于N的线程池大小。

但是在具体的工作开发中,这个东西是很难通过看代码来确定的,因为任务会很复杂,大概率是cpu和io同时都有,所以综上所述,最好的方法就是通过实验来确定。设置多大的合适,对于性能的提升最大。

实践是检验真理的唯一标准!

4.手动写一个线程池

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.BlockingQueue;

 class MyThreadPoolExcutor {
    private BlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(1000);
    private List<Thread> list = new ArrayList<>();

    public MyThreadPoolExcutor(int a){

        for (int i = 0; i < a; i++) {
            Thread t =new Thread(()->{
                while (true){
                    try {
                       Runnable runnable =queue.take();
                       runnable.run();
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }

            });
            t.start();
            list.add(t);
        }
    }
    public void submit(Runnable runnable) throws InterruptedException {
        queue.put(runnable);
    }
}
public class MyThreadExcutor {
    public static void main(String[] args) throws InterruptedException {
        MyThreadPoolExcutor myThreadPoolExcutor = new MyThreadPoolExcutor(4);
        for (int i =0; i < 1000; i++) {
            int a= i;
            myThreadPoolExcutor.submit(new Runnable() {
                @Override
                public void run() {
                    System.out.println("打印变量" + a +"执行的线程为" + Thread.currentThread().getName());
                }
            });
        }


    }
}

在上述代码里,我们手动创建了一个线程池,是固定线程的线程池。里面有一个带阻塞功能的任务队列,当我们put进去新的任务的时候,会进入到任务队列中。然后线程池里的线程就会执行这个任务,至于是哪个线程,是随机的一个。

这段代码实现了一个简单的线程池,能够并发执行多个任务,而不需要为每个任务都创建一个新的线程。

                                                                                                                                                  

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

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

相关文章

理解JSX:提高前端开发效率的关键(下)

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

CGAL的最优传输曲线重构

1、介绍 此程序包实现了一种重建和简化二维点集的方法。输入是一组具有质量属性的二维点&#xff0c;可能受到噪声和离群值的干扰。输出是一组线段和孤立点&#xff0c;它们近似于输入点&#xff0c;如下图所示。质量属性与每个点的近似重要性有关。 左&#xff1a;输入点集受到…

SWPU NSS新生赛

&#x1f60b;大家好&#xff0c;我是YAy_17&#xff0c;是一枚爱好网安的小白&#xff0c;正在自学ing。 本人水平有限&#xff0c;欢迎各位大佬指点&#xff0c;一起学习&#x1f497;&#xff0c;一起进步⭐️。 ⭐️此后如竟没有炬火&#xff0c;我便是唯一的光。⭐️ 最近…

网页图标素材免费下载网站

这里是几个可以免费下载网页图标素材的的网站。这些个网站里的图表和素材&#xff0c;应该是都可以免费下载的。&#xff08;至少我下载了几个素材是没有花钱的&#xff09; Flaticon iconArchive freepik 4. iconmonstr 5. Icons and Photos For Everything 如果想下载图片&a…

在项目中,使用drawio创建一个共享协作看板

在项目中&#xff0c;使用drawio创建一个共享协作看板 drawio是一款强大的图表绘制软件&#xff0c;支持在线云端版本以及windows, macOS, linux安装版。 如果想在线直接使用&#xff0c;则直接输入网址draw.io或者使用drawon(桌案), drawon.cn内部完整的集成了drawio的所有功…

【C语言(十一)】

C语言内存函数 一、memcpy使用和模拟实现 void * memcpy ( void * destination, const void * source, size_t num ); • 函数memcpy从source的位置开始向后复制num个字节的数据到destination指向的内存位置。 • 这个函数在遇到 \0 的时候并不会停下来。 • 如果sourc…

【每日一题】【12.14】2132.用邮票贴满网格图

&#x1f525;博客主页&#xff1a; A_SHOWY&#x1f3a5;系列专栏&#xff1a;力扣刷题总结录 数据结构 云计算 数字图像处理 力扣每日一题_ 2132. 用邮票贴满网格图https://leetcode.cn/problems/stamping-the-grid/ 今天的每日一题又是一道恶心的困难题目&#xff0c;花…

【数据结构期末复习】完善中

文章目录 二叉树的三种遍历方式怎么看遍历结果相关题目&#xff1a;已知一颗二叉树的后续遍历序列为&#xff1a;GFEDCBA;中序遍历序列为&#xff1a;FGAEBDC。画出这棵二叉树思路代码版 先序线索树二叉树转树、或森林树转二叉树二叉树转树二叉树转森林森林转二叉树 二叉树的三…

Java之BigDecimal详解

一、BigDecimal概述 Java在java.math包中提供的API类BigDecimal&#xff0c;用来对超过16位有效位的数进行精确的运算。双精度浮点型变量double可以处理16位有效数&#xff0c;但在实际应用中&#xff0c;可能需要对更大或者更小的数进行运算和处理。一般情况下&#xff0c;对…

阿里云人工智能平台PAI多篇论文入选EMNLP 2023

近期&#xff0c;阿里云人工智能平台PAI主导的多篇论文在EMNLP2023上入选。EMNLP是人工智能自然语言处理领域的顶级国际会议&#xff0c;聚焦于自然语言处理技术在各个应用场景的学术研究&#xff0c;尤其重视自然语言处理的实证研究。该会议曾推动了预训练语言模型、文本挖掘、…

【基于卷积神经网络的疲劳检测与预警系统的设计与实现】

基于卷积神经网络的疲劳检测与预警系统的设计与实现 引言数据集介绍技术与工具1. OpenCV2. TensorFlow3. 卷积神经网络&#xff08;CNN&#xff09; 系统功能模块1. 视频采集模块2. 图像预处理模块3. 人脸识别模块4. 疲劳程度判别模块5. 报警模块 系统设计创新点1. 实时监测与预…

js解析.shp文件

效果图 原理与源码 本文采用的是shapefile.js工具 这里是他的npm地址 https://www.npmjs.com/package/shapefile 这是他的unpkg地址&#xff0c;可以点开查看源码 https://unpkg.com/shapefile0.6.6/dist/shapefile.js 这个最关键的核心问题是如何用这个工具&#xff0c;网上…

如何正确使用缓存来提升系统性能

文章目录 引言什么时候适合加缓存&#xff1f;示例1示例2&#xff1a;示例3&#xff1a; 缓存应该怎么配置&#xff1f;数据分布**缓存容量大小&#xff1a;**数据淘汰策略 缓存的副作用总结 引言 在上一篇文章IO密集型服务提升性能的三种方法中&#xff0c;我们提到了三种优化…

如何在iPad Pro上实现SSH远程连接服务器并进行云端编程开发【内网穿透】

文章目录 前言1. 在iPad下载Code APP2.安装cpolar内网穿透2.1 cpolar 安装2.2 创建TCP隧道 3. iPad远程vscode4. 配置固定TCP端口地址4.1 保留固定TCP地址4.2 配置固定的TCP端口地址4.3 使用固定TCP地址远程vscode 前言 本文主要介绍开源iPad应用IDE如何下载安装&#xff0c;并…

京微齐力:基于H7的平衡控制系统(一、姿态解析)

目录 前言一、关于平衡控制系统二、实验效果三、硬件选择1、H7P20N0L176-M2H12、MPU6050 四、理论简述五、程序设计1、Cordic算法2、MPU6050采集数据3、fir&iir滤波4、姿态解算 六、资源消耗&工程获取七、总结 前言 很久之前&#xff0c;就想用纯FPGA做一套控制系统。可…

9.2 Linux LED 驱动开发

一、Linux 下的 LED 驱动原理 Linux 下的任何驱动&#xff0c;最后都是要配置相应的硬件寄存器。 1. 地址映射 MMU 全称叫做 MemoryManage Unit&#xff0c;也就是内存管理单元。 现在的 Linux 支持无 MMU 处理器。MMU 主要完成的功能为&#xff1a; 1、完成虚拟空间到物理空间…

香港科技大学数据建模(MSc DDM)硕士学位项目(2024年秋季入学)招生宣讲会-四川大学专场

时间&#xff1a;2023 年 12 月 26 日&#xff08;周二&#xff09; 14:30 地点&#xff1a;四川大学望江校区基础教学楼 C 座 102 嘉宾教授&#xff1a;潘鼎 教授 项目旨在培养科学或工程背景的学员从数据中提取信息的数据建模能力&#xff0c;训练其拥有优秀的解难和逻辑思…

旅游景区文旅地产如何通过数字人开启数字营销?

随着元宇宙的发展&#xff0c;为虚实相生的营销带来更多的可能性。基于虚拟世界对于现实世界的模仿&#xff0c;通过构建沉浸式数字体验&#xff0c;增强现实生活的数字体验&#xff0c;强调实现真实体验的数字化&#xff0c;让品牌结合数字人开启数字化营销。 *图片源于网络 …

谷歌浏览器怎么关闭自动更新?

文章目录 一、方式一 谷歌浏览器安装完成后&#xff0c;每天都会自动更新到最新的版本&#xff0c;但是对于有些程序的驱动&#xff0c;浏览器一更新就不能自动启动浏览器&#xff0c;会给我们带来很多困扰。下面我们介绍怎么将谷歌浏览器自动更新关闭&#xff0c;如果需要更新…

# 和 $ 的区别②

上节博客说了使用 # 的时候,如果参数为 String ,会自动加上单引号 但是当参数为String 类型的时候,也有不需要加单引号的情况,这时候用 # 那就会出问题 比如根据 升序(asc) 或者 降序(desc) 查找的时候,加了单引号那就会报错 这个时候我们就只能使用 $ 如果看不懂代码,就去…