当前位置: 首页 > news >正文

线程池的使用——线程池的创建方式

线程池的使用——创建线程

  • 线程池的创建
  • 线程池的创建方式
    • Executors.newFixedThreadPool:
    • Executors.newCachedThreadPool:
    • Executors.newSingleThreadExecutor:
    • Executors.newScheduledThreadPool:
    • Executors.newSingleThreadScheduledExecutor:
    • Executors.newWorkStealingPool:
    • ThreadPoolExecutor:
  • 线程池的拒绝策略
      • ThreadPoolExecutor.AbortPolicy:
      • ThreadPoolExecutor.DiscardPolicy:
      • ThreadPoolExecutor.DiscardOldestPolicy:
      • ThreadPoolExecutor.CallerRunsPolicy:

线程池的创建

线程池的创建方法总共有 7 种,但总体来说可分为 2 类:

  • 一类是通过 ThreadPoolExecutor 创建的线程池;
  • 另一个类是通过 Executors 创建的线程池。

线程池的创建方式

Executors.newFixedThreadPool:

创建一个固定大小的线程池,可控制并发的线程数,超出的线程会在队列中等待

//      创建一个固定大小的线程池,可控制并发的线程数,超出的线程会在队列中等待ExecutorService executorService = Executors.newFixedThreadPool(3);// 创建任务Runnable runnable = new Runnable() {@Overridepublic void run() {System.out.println("任务被执行,线程:" + Thread.currentThread().getName());}};executorService.submit(runnable);  // 执行方式 1:submitexecutorService.execute(runnable); // 执行方式 2:executeexecutorService.execute(runnable);executorService.execute(runnable);//结束线程池executorService.shutdown();

执行结果如下:
超出线程数量的任务会在队列中等待,其他任务执行完毕之后再获取线程执行任务。

任务被执行,线程:pool-1-thread-1
任务被执行,线程:pool-1-thread-3
任务被执行,线程:pool-1-thread-2
任务被执行,线程:pool-1-thread-3

Executors.newCachedThreadPool:

创建一个可缓存的线程池,若线程数超过处理所需,缓存一段时间后会回收,若线程数不够,则新建线程;

        ExecutorService executorService = Executors.newCachedThreadPool(Executors.defaultThreadFactory());// 创建任务Runnable runnable = new Runnable() {@Overridepublic void run() {System.out.println("任务被执行,线程:" + Thread.currentThread().getName());}};// 线程池执行任务(一次添加 4 个任务)// 执行任务的方法有两种:submit 和 executefor (int i = 0; i < 10 ; i++) {executorService.submit(runnable);  // 执行方式 1:submitexecutorService.execute(runnable); // 执行方式 2:executeexecutorService.execute(runnable);executorService.execute(runnable);}executorService.shutdown();

运行结果如下:

任务被执行,线程:pool-1-thread-1
任务被执行,线程:pool-1-thread-1
任务被执行,线程:pool-1-thread-3
任务被执行,线程:pool-1-thread-4
任务被执行,线程:pool-1-thread-2
任务被执行,线程:pool-1-thread-5
任务被执行,线程:pool-1-thread-6
任务被执行,线程:pool-1-thread-7
任务被执行,线程:pool-1-thread-9
任务被执行,线程:pool-1-thread-10
任务被执行,线程:pool-1-thread-14
任务被执行,线程:pool-1-thread-13
任务被执行,线程:pool-1-thread-15
任务被执行,线程:pool-1-thread-16
任务被执行,线程:pool-1-thread-18
任务被执行,线程:pool-1-thread-20
任务被执行,线程:pool-1-thread-17
任务被执行,线程:pool-1-thread-22
任务被执行,线程:pool-1-thread-23
任务被执行,线程:pool-1-thread-25
任务被执行,线程:pool-1-thread-27
任务被执行,线程:pool-1-thread-28
任务被执行,线程:pool-1-thread-30
任务被执行,线程:pool-1-thread-29
任务被执行,线程:pool-1-thread-32
任务被执行,线程:pool-1-thread-31
任务被执行,线程:pool-1-thread-33
任务被执行,线程:pool-1-thread-35
任务被执行,线程:pool-1-thread-39
任务被执行,线程:pool-1-thread-36
任务被执行,线程:pool-1-thread-8
任务被执行,线程:pool-1-thread-19
任务被执行,线程:pool-1-thread-21
任务被执行,线程:pool-1-thread-24
任务被执行,线程:pool-1-thread-34
任务被执行,线程:pool-1-thread-38
任务被执行,线程:pool-1-thread-11
任务被执行,线程:pool-1-thread-12
任务被执行,线程:pool-1-thread-26
任务被执行,线程:pool-1-thread-37

Executors.newSingleThreadExecutor:

创建单个线程数的线程池,它可以保证先进先出的执行顺序;

  ExecutorService executorService = Executors.newSingleThreadExecutor(Executors.defaultThreadFactory());// 创建任务Runnable runnable = new Runnable() {@Overridepublic void run() {System.out.println("任务被执行,线程:" + Thread.currentThread().getName());}};// 线程池执行任务(一次添加 4 个任务)// 执行任务的方法有两种:submit 和 executefor (int i = 0; i < 10 ; i++) {executorService.submit(runnable);  // 执行方式 1:submitexecutorService.execute(runnable); // 执行方式 2:executeexecutorService.execute(runnable);executorService.execute(runnable);}executorService.shutdown();

执行结果如下

任务被执行,线程:pool-1-thread-1
任务被执行,线程:pool-1-thread-1
任务被执行,线程:pool-1-thread-1
任务被执行,线程:pool-1-thread-1
任务被执行,线程:pool-1-thread-1
任务被执行,线程:pool-1-thread-1
...

Executors.newScheduledThreadPool:

创建一个可以执行延迟任务的线程池;

      ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(3);System.out.println("任务添加时间"+ new Date());ScheduledFuture<Date> schedul = scheduledExecutorService.schedule(()->{return new Date();}, 3, TimeUnit.SECONDS);System.out.println("任务执行完毕" + schedul.get());

运行结果如下:

在2秒钟后执行一次任务,线程阻塞等待结果返回。执行完成并返回结果后就结束。

任务添加时间Thu Mar 02 20:50:12 CST 2023
任务执行完毕Thu Mar 02 20:50:15 CST 2023

Executors.newSingleThreadScheduledExecutor:

创建一个单线程的可以执行延迟任务的线程池;

public static void SingleThreadScheduledExecutor() {// 创建线程池ScheduledExecutorService threadPool = Executors.newSingleThreadScheduledExecutor();// 添加定时执行任务(2s 后执行)System.out.println("添加任务,时间:" + new Date());threadPool.schedule(() -> {System.out.println("任务被执行,时间:" + new Date());try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {}}, 2, TimeUnit.SECONDS);
}

执行结果如下:
在这里插入图片描述

Executors.newWorkStealingPool:

创建一个抢占式执行的线程池(任务执行顺序不确定)【JDK 1.8 添加】。

public static void workStealingPool() {// 创建线程池ExecutorService threadPool = Executors.newWorkStealingPool();// 执行任务for (int i = 0; i < 10; i++) {final int index = i;threadPool.execute(() -> {System.out.println(index + " 被执行,线程名:" + Thread.currentThread().getName());});}// 确保任务执行完成while (!threadPool.isTerminated()) {}
}

运行结果如下:
从上述结果可以看出,任务的执行顺序是不确定的,因为它是抢占式执行的。
在这里插入图片描述

ThreadPoolExecutor:

最原始的创建线程池的方式,它包含了 7 个参数可供设置。

public static void myThreadPoolExecutor() {// 创建线程池ThreadPoolExecutor threadPool = new ThreadPoolExecutor(5, 10, 100, TimeUnit.SECONDS, new LinkedBlockingQueue<>(10));// 执行任务for (int i = 0; i < 10; i++) {final int index = i;threadPool.execute(() -> {System.out.println(index + " 被执行,线程名:" + Thread.currentThread().getName());try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}});}
}

执行结果如下:
在这里插入图片描述

线程池的拒绝策略

当线程池的任务缓存队列已满并且线程池中的线程数目达到maximumPoolSize时,如果还有任务到来就会采取任务拒绝策略,通常有以下四种策略:

ThreadPoolExecutor.AbortPolicy:

丢弃任务并抛出RejectedExecutionException异常。

ThreadPoolExecutor.DiscardPolicy:

丢弃任务,但是不抛出异常。

ThreadPoolExecutor.DiscardOldestPolicy:

丢弃队列最前面的任务,然后重新提交被拒绝的任务

ThreadPoolExecutor.CallerRunsPolicy:

由调用线程(提交任务的线程)处理该任务

相关文章:

线程池的使用——线程池的创建方式

线程池的使用——创建线程线程池的创建线程池的创建方式Executors.newFixedThreadPool&#xff1a;Executors.newCachedThreadPool&#xff1a;Executors.newSingleThreadExecutor&#xff1a;Executors.newScheduledThreadPool&#xff1a;Executors.newSingleThreadScheduled…...

代码随想录算法训练营day47 |动态规划 198打家劫舍 213打家劫舍II 337打家劫舍III

day47198.打家劫舍1.确定dp数组&#xff08;dp table&#xff09;以及下标的含义2.确定递推公式3.dp数组如何初始化4.确定遍历顺序5.举例推导dp数组213.打家劫舍II情况一&#xff1a;考虑不包含首尾元素情况二&#xff1a;考虑包含首元素&#xff0c;不包含尾元素情况三&#x…...

项目设计模式和规范

1、责任链模式 自己的理解:避免发生方与接收方解耦 优点:①降低发送方与接收方的耦合 ②简化他们对象 ③方便扩展新增 处理者 缺点:①不方便排错 ②性能问题,且使用不当容易搞出死循环 应用场景:拦截器 Interceptor和过滤器 filter:符合模式的进行拦截或者过滤到,然…...

无线WiFi安全渗透与攻防(一)之无线安全环境搭建

无线安全环境搭建 1.802.11标准 &#xff08;1&#xff09;.概念 802.11标准是1997年IEEE最初制定的一个WLAN标准&#xff0c;工作在2.4GHz开放频段&#xff0c;支持1Mbit/s和2Mbit/s的数据传输速率&#xff0c;定义了物理层和MAC层规范&#xff0c;允许无线局域网及无线设备…...

【matplotlib】可视化解决方案——如何解决matplotlib中文乱码问题

问题概述 Matplotlib 默认不支持中文字体&#xff0c;这是因为 matplotlib 只支持 ASCII 字符&#xff0c;但是国人使用 matplotlib 肯定需要中文标注。如下图所示&#xff0c;当不对 Matplotlib 进行设置&#xff0c;而直接使用中文时&#xff0c;绘制的图像会出现中文乱码。…...

JAVA开发中GC日志打印简单通用的配置详解

如何配置一个完美的JVM日志打印信息 打印内容 打印基本的GC信息 打印对象分布情况 GC后打印堆数据 打印STW时间 打印safepoint信息 打印Reference处理信息 综上所述&#xff0c;最终的参数如下&#xff1a; 还有哪些问题呢&#xff1f;是不是有文件输出更好&#xff1f; 打印日…...

十进制的小数如何转二进制?二进制表示的小数如何转十进制?

😄 基础不牢,地动山摇~ 补补基础~ 文章目录 1、十进制的小数转二进制?2、二进制表示的小数转十进制?3、做道coding题巩固下:1、十进制的小数转二进制? 整数部分: 用普通的二进制表示即可。小数部分: 首先,将小数部分乘以2,取出整数部分作为二进制表示的第1位;然后…...

klipper使用webcam设置多个摄像头方式

一、前言 使用klipper设置多个摄像头&#xff0c;折腾了好些天&#xff0c;网上资料很少&#xff0c;这里写一个帖子记录一下 二、环境 参考链接&#xff1a;https://www.cnblogs.com/sjqlwy/p/klipper_webcam.html 我的klipper安装在香橙派上面&#xff0c;系统是debian&a…...

风力发电机组浪涌保护器安全防护方案

风机的庞大与危险高空作业注定了其在基建和维护中不易操作&#xff0c;风机设备的主电源、过程控制、网络与通讯、现场设备需要高等级的防雷浪涌保护器冲击保护&#xff0c;提高系统及设备的可靠性和可用性。风电场的主要发电设备风力发电机组“大风车”是风电场的主要发电设备…...

【剑指offer】JZ7 重建二叉树、JZ9 用两个栈实现队列

\描述&#xff1a; 给定节点数为 n 的二叉树的前序遍历和中序遍历结果&#xff0c;请重建出该二叉树并返回它的头结点。 例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6}&#xff0c;则重建出如下图所示。 思路&#xff1a; 题上给了我们前序遍历(根 …...

ElasticSearch - SpringBoot整合ES之查询所有 match_all

文章目录1. 数据准备2. 全量查询 match_all3. 使用 boost 参数更改 _score官方文档地址&#xff1a;https://www.elastic.co/guide/en/elasticsearch/reference/index.html权威指南&#xff1a;https://www.elastic.co/guide/cn/elasticsearch/guide/current/structured-search…...

详谈IIC

前言 在嵌入式底层系统中&#xff0c;常见的通讯方式&#xff0c;串口&#xff0c;IIC&#xff0c;SPI&#xff0c;IIS等&#xff0c;一般IIC,SPI,IIS更多的采取IO模拟&#xff0c;其余CAN,UART均是硬件设计直接支持&#xff0c;而IIC主要用于多数传感器数据的读写&#xff0c…...

【Autoware】采集实验数据bag包并仿真运行

文章目录1. 官方demo包2. 控制底层地图采集3. 感知定位4. 规划控制5. 仿真或实车运行1. 官方demo包 wget http://db3.ertl.jp/autoware/sample_data/sample_moriyama_data.tar.gz wget http://db3.ertl.jp/autoware/sample_data/sample_moriyama_150324.tar.gz官方示例包的网上…...

名创优品怎么把创意做成生意?

最近&#xff0c;“主”无处不在&#xff0c;从让“依托答辩”梗火出圈的动画《三体》&#xff0c;到备受好评的电视剧《三体》&#xff0c;再到仍在刷新高票房成绩的《流浪地球2》。作为近些年来中国为数不多的爆款IP制造者&#xff0c;刘慈欣在《三体》中提出了一个著名的理论…...

springboot原项目配置文件迁移至nacos

目录一、配置文件迁移nacos1.安装nacos2.添加依赖3.改造service-product3.改造server-gateway一、配置文件迁移nacos 1.安装nacos 1&#xff0c;如果之前安装过nacos&#xff0c;nacos数据保存至mysql&#xff0c;先删除已安装的nacos&#xff0c;再安装 docker stop nacos …...

常用的shell脚步操作

文章目录一、如何开始一个shell脚本?1.基本语法2.变量定义规则二、特色变量1.$n2.$&#xff1f;三、条件判断1&#xff0e;基本语法2.运算符if,for,while四、字符串切割1.从指定位置开始截取从字符串左边开始计数从右边开始计数2.从指定字符&#xff08;子字符串&#xff09;开…...

Java on VS Code 2月更新|JUnit 5 并行测试与 Spring Boot 插件的过滤功能

作者&#xff1a;Nick Zhu - Senior Program Manager, Developer Division at Microsoft 排版&#xff1a;Alan Wang 大家好&#xff0c;欢迎来到我们的二月更新&#xff01;在此博客中&#xff0c;我们将为您带来与 JUnit 5 并行测试相关的新功能以及用于 Spring Boot Dashboa…...

无线WiFi安全渗透与攻防(三)之Windows扫描wifi和破解WiFi密码

系列文章 无线WiFi安全渗透与攻防(一)之无线安全环境搭建 无线WiFi安全渗透与攻防(二)之打造专属字典 windows下wifi进行扫描和破解 1.wifi扫描 &#xff08;1&#xff09;.软件介绍 WirelessMon是一款无线网络扫描工具&#xff0c;它可以帮助用户扫描附近的无线信号&…...

Python中的遍历字典的键和值

一、Python的字典在项目的开发过程中&#xff0c;如果遇到有映射关系的内容可以考虑使用Python中的字典进行存储数据&#xff0c;字典中冒号前的数据称为【键】、冒号后的数据称为【值】。二、Python字典的用法2.1、Python的定义#Python字典的定义 字典名称{键1:值1,键2:值2,键…...

三天Golang快速入门—结构体

Struct结构体什么是结构体结构体定义基本实例化new实例化键值对初始化结构体方法和接收者结构体说明结构体方法和接收者值类型和指针类型接收者struct与jsonstruct转json字符串json转structstruct tagTag结构体转化Json字符串Json字符串转成Tag结构体什么是结构体 1.Golang中没…...

python打卡day49

知识点回顾&#xff1a; 通道注意力模块复习空间注意力模块CBAM的定义 作业&#xff1a;尝试对今天的模型检查参数数目&#xff0c;并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...

Spring Boot 实现流式响应(兼容 2.7.x)

在实际开发中&#xff0c;我们可能会遇到一些流式数据处理的场景&#xff0c;比如接收来自上游接口的 Server-Sent Events&#xff08;SSE&#xff09; 或 流式 JSON 内容&#xff0c;并将其原样中转给前端页面或客户端。这种情况下&#xff0c;传统的 RestTemplate 缓存机制会…...

2021-03-15 iview一些问题

1.iview 在使用tree组件时&#xff0c;发现没有set类的方法&#xff0c;只有get&#xff0c;那么要改变tree值&#xff0c;只能遍历treeData&#xff0c;递归修改treeData的checked&#xff0c;发现无法更改&#xff0c;原因在于check模式下&#xff0c;子元素的勾选状态跟父节…...

css的定位(position)详解:相对定位 绝对定位 固定定位

在 CSS 中&#xff0c;元素的定位通过 position 属性控制&#xff0c;共有 5 种定位模式&#xff1a;static&#xff08;静态定位&#xff09;、relative&#xff08;相对定位&#xff09;、absolute&#xff08;绝对定位&#xff09;、fixed&#xff08;固定定位&#xff09;和…...

用机器学习破解新能源领域的“弃风”难题

音乐发烧友深有体会&#xff0c;玩音乐的本质就是玩电网。火电声音偏暖&#xff0c;水电偏冷&#xff0c;风电偏空旷。至于太阳能发的电&#xff0c;则略显朦胧和单薄。 不知你是否有感觉&#xff0c;近两年家里的音响声音越来越冷&#xff0c;听起来越来越单薄&#xff1f; —…...

Docker 本地安装 mysql 数据库

Docker: Accelerated Container Application Development 下载对应操作系统版本的 docker &#xff1b;并安装。 基础操作不再赘述。 打开 macOS 终端&#xff0c;开始 docker 安装mysql之旅 第一步 docker search mysql 》〉docker search mysql NAME DE…...

VM虚拟机网络配置(ubuntu24桥接模式):配置静态IP

编辑-虚拟网络编辑器-更改设置 选择桥接模式&#xff0c;然后找到相应的网卡&#xff08;可以查看自己本机的网络连接&#xff09; windows连接的网络点击查看属性 编辑虚拟机设置更改网络配置&#xff0c;选择刚才配置的桥接模式 静态ip设置&#xff1a; 我用的ubuntu24桌…...

人工智能(大型语言模型 LLMs)对不同学科的影响以及由此产生的新学习方式

今天是关于AI如何在教学中增强学生的学习体验&#xff0c;我把重要信息标红了。人文学科的价值被低估了 ⬇️ 转型与必要性 人工智能正在深刻地改变教育&#xff0c;这并非炒作&#xff0c;而是已经发生的巨大变革。教育机构和教育者不能忽视它&#xff0c;试图简单地禁止学生使…...

搭建DNS域名解析服务器(正向解析资源文件)

正向解析资源文件 1&#xff09;准备工作 服务端及客户端都关闭安全软件 [rootlocalhost ~]# systemctl stop firewalld [rootlocalhost ~]# setenforce 0 2&#xff09;服务端安装软件&#xff1a;bind 1.配置yum源 [rootlocalhost ~]# cat /etc/yum.repos.d/base.repo [Base…...

Git常用命令完全指南:从入门到精通

Git常用命令完全指南&#xff1a;从入门到精通 一、基础配置命令 1. 用户信息配置 # 设置全局用户名 git config --global user.name "你的名字"# 设置全局邮箱 git config --global user.email "你的邮箱example.com"# 查看所有配置 git config --list…...