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

深入理解高并发编程 - 分析创建线程池究竟有哪些方式

1、使用Executors工厂方法:

使用Executors工厂方法创建线程池是一种简单快捷的方式,适用于一些常见的线程池需求。以下是几个示例,演示如何使用Executors工厂方法创建不同类型的线程池:

固定大小线程池 (newFixedThreadPool):

这种类型的线程池会一直保持固定数量的线程在池中,不会自动回收线程。适用于需要限制同时执行的任务数量的场景。

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class FixedThreadPoolExample {public static void main(String[] args) {int numThreads = 5;ExecutorService executor = Executors.newFixedThreadPool(numThreads);// 提交任务到线程池for (int i = 0; i < 10; i++) {executor.submit(new MyRunnable(i));}executor.shutdown(); // 关闭线程池}
}

缓存线程池 (newCachedThreadPool):

缓存线程池会根据需要创建新的线程,如果线程池中的线程空闲时间超过指定的时间,则会被回收。适用于任务数量不确定,且需要自动调整线程数的场景。

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class CachedThreadPoolExample {public static void main(String[] args) {ExecutorService executor = Executors.newCachedThreadPool();// 提交任务到线程池for (int i = 0; i < 10; i++) {executor.submit(new MyRunnable(i));}executor.shutdown(); // 关闭线程池}
}

单线程线程池 (newSingleThreadExecutor):

单线程线程池只有一个工作线程,适用于需要按顺序执行任务的场景。

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class SingleThreadExecutorExample {public static void main(String[] args) {ExecutorService executor = Executors.newSingleThreadExecutor();// 提交任务到线程池for (int i = 0; i < 10; i++) {executor.submit(new MyRunnable(i));}executor.shutdown(); // 关闭线程池}
}

定时任务线程池 (newScheduledThreadPool):

定时任务线程池用于执行定时任务和周期性任务。

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;public class ScheduledThreadPoolExample {public static void main(String[] args) {int numThreads = 3;ScheduledExecutorService executor = Executors.newScheduledThreadPool(numThreads);// 延迟1秒后执行任务executor.schedule(new MyRunnable(1), 1, TimeUnit.SECONDS);// 延迟2秒后,每3秒执行一次任务executor.scheduleAtFixedRate(new MyRunnable(2), 2, 3, TimeUnit.SECONDS);// 关闭线程池executor.shutdown();}
}

在这些示例中,MyRunnable是一个实现了Runnable接口的自定义任务类。创建线程池后,使用submit方法将任务提交给线程池进行执行,并最终调用shutdown方法关闭线程池。

这些Executors工厂方法提供了一些常见的线程池类型,但在某些情况下,可能需要更精细的线程池配置,这时可以考虑手动创建ThreadPoolExecutor。

2、手动创建ThreadPoolExecutor:

手动创建 ThreadPoolExecutor 允许对线程池的各种参数进行更精细的配置,以满足特定的需求。以下是一个示例,演示如何手动创建 ThreadPoolExecutor:

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;public class ManualThreadPoolExecutorExample {public static void main(String[] args) {int corePoolSize = 5;int maxPoolSize = 10;long keepAliveTime = 60; // 60秒TimeUnit timeUnit = TimeUnit.SECONDS;BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>();ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize, maxPoolSize, keepAliveTime, timeUnit, workQueue);// 提交任务到线程池for (int i = 0; i < 10; i++) {executor.submit(new MyRunnable(i));}executor.shutdown(); // 关闭线程池}
}class MyRunnable implements Runnable {private int id;public MyRunnable(int id) {this.id = id;}@Overridepublic void run() {System.out.println("Task " + id + " is running on thread " + Thread.currentThread().getName());}
}

在这个示例中,手动创建了一个 ThreadPoolExecutor,并配置了核心线程数、最大线程数、线程空闲时间等参数。然后,使用 submit 方法将任务提交给线程池进行执行,并最终调用 shutdown 方法关闭线程池。

注意,BlockingQueue 参数用于指定任务队列,用来存储等待执行的任务。在这里,使用了 LinkedBlockingQueue,也可以选择其他的实现,如 ArrayBlockingQueue、PriorityBlockingQueue 等,以适应不同的需求。

手动创建 ThreadPoolExecutor 允许更精细地控制线程池的行为,但也需要更多的配置和管理。在选择线程池类型和参数时,应根据应用的特性和需求进行调整。

3、使用ForkJoinPool:

ForkJoinPool 是 Java 提供的用于支持分治任务的线程池实现。它特别适用于能够将任务拆分成更小的子任务,并且这些子任务可以并行执行的情况。以下是一个使用 ForkJoinPool 创建线程池的示例:

import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveAction;public class ForkJoinPoolExample {public static void main(String[] args) {ForkJoinPool forkJoinPool = new ForkJoinPool();MyRecursiveAction task = new MyRecursiveAction(0, 10);forkJoinPool.invoke(task);forkJoinPool.shutdown();}
}class MyRecursiveAction extends RecursiveAction {private static final int THRESHOLD = 2; // 阈值,小于该值就不再分解任务private int start;private int end;public MyRecursiveAction(int start, int end) {this.start = start;this.end = end;}@Overrideprotected void compute() {if (end - start <= THRESHOLD) {// 执行任务逻辑for (int i = start; i <= end; i++) {System.out.println("Task is running on thread " + Thread.currentThread().getName() + ": " + i);}} else {// 分解任务int mid = (start + end) / 2;MyRecursiveAction left = new MyRecursiveAction(start, mid);MyRecursiveAction right = new MyRecursiveAction(mid + 1, end);invokeAll(left, right);}}
}

在这个示例中,首先创建了一个 ForkJoinPool 实例,然后定义了一个继承自 RecursiveAction 的 MyRecursiveAction 类,用于表示要执行的分治任务。在 compute 方法中,首先检查任务是否足够小,如果是,则执行任务逻辑;否则,将任务分解为两个子任务并使用 invokeAll 方法并行执行。

ForkJoinPool 会根据任务的大小和可用线程数来动态地调度任务的执行,以获得最佳的并行性能。在实际使用中,可以根据任务的特性和复杂度调整阈值,以及分解和执行子任务的逻辑。

注意,ForkJoinPool 适用于能够利用分治并行计算的场景,如递归问题的解决和并行计算任务。

4、使用 ScheduledThreadPoolExecutor 类

ScheduledThreadPoolExecutor 是 ThreadPoolExecutor 的子类,专门用于创建带有定时任务功能的线程池。它可以执行定时任务和周期性任务。以下是一个使用 ScheduledThreadPoolExecutor 创建线程池的示例:

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;public class ScheduledThreadPoolExecutorExample {public static void main(String[] args) {int numThreads = 3;ScheduledExecutorService executor = Executors.newScheduledThreadPool(numThreads);// 延迟1秒后执行任务executor.schedule(new MyRunnable(1), 1, TimeUnit.SECONDS);// 延迟2秒后,每3秒执行一次任务executor.scheduleAtFixedRate(new MyRunnable(2), 2, 3, TimeUnit.SECONDS);// 关闭线程池executor.shutdown();}
}class MyRunnable implements Runnable {private int id;public MyRunnable(int id) {this.id = id;}@Overridepublic void run() {System.out.println("Task " + id + " is running on thread " + Thread.currentThread().getName());}
}

在这个示例中,使用 Executors.newScheduledThreadPool() 方法创建了一个 ScheduledExecutorService,然后使用 schedule 方法在指定的延迟时间后执行一次任务,使用 scheduleAtFixedRate 方法在指定的延迟时间后开始执行任务,并且每隔一段时间重复执行。

ScheduledThreadPoolExecutor 可以满足定时任务和周期性任务的需求,它能够自动调度任务的执行。当任务执行时间超过任务间隔时间时,ScheduledThreadPoolExecutor 会等待当前任务完成后再启动下一个任务。这种特性对于需要保证任务执行间隔的场景非常有用。

5、使用第三方库(如ThreadPoolExecutor的封装库):

许多第三方库都提供了对 ThreadPoolExecutor 的封装,以便更方便地创建和管理线程池。其中一个常用的库是 Apache Commons Lang 中的 ThreadPoolExecutor,它提供了一些额外的功能和配置选项。以下是一个使用 Apache Commons Lang 的 ThreadPoolExecutor 封装库的示例:

首先,确保已经将 Apache Commons Lang 库添加到项目中。然后,你可以使用 org.apache.commons.lang3.concurrent.BasicThreadFactory 来创建线程池。下面是示例代码:

import org.apache.commons.lang3.concurrent.BasicThreadFactory;import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;public class ThirdPartyThreadPoolExample {public static void main(String[] args) {int numThreads = 3;BasicThreadFactory factory = new BasicThreadFactory.Builder().namingPattern("my-pool-%d").daemon(true).build();ScheduledExecutorService executor = new ScheduledThreadPoolExecutor(numThreads, factory);// 延迟1秒后执行任务executor.schedule(new MyRunnable(1), 1, TimeUnit.SECONDS);// 延迟2秒后,每3秒执行一次任务executor.scheduleAtFixedRate(new MyRunnable(2), 2, 3, TimeUnit.SECONDS);// 关闭线程池executor.shutdown();}
}class MyRunnable implements Runnable {private int id;public MyRunnable(int id) {this.id = id;}@Overridepublic void run() {System.out.println("Task " + id + " is running on thread " + Thread.currentThread().getName());}
}

在这个示例中,使用 BasicThreadFactory 来配置线程池。通过设置不同的属性,可以定制线程名、守护线程属性等。然后,使用 ScheduledThreadPoolExecutor 创建一个带有定时任务功能的线程池,并使用 schedule 和 scheduleAtFixedRate 方法添加定时任务。

使用第三方库的线程池封装可以帮助更方便地创建和管理线程池,以及提供一些额外的功能选项。

相关文章:

深入理解高并发编程 - 分析创建线程池究竟有哪些方式

1、使用Executors工厂方法&#xff1a; 使用Executors工厂方法创建线程池是一种简单快捷的方式&#xff0c;适用于一些常见的线程池需求。以下是几个示例&#xff0c;演示如何使用Executors工厂方法创建不同类型的线程池&#xff1a; 固定大小线程池 (newFixedThreadPool)&am…...

Kafka第一课概述与安装

生产经验 面试重点 Broker面试重点 代码,开发重点 67 章了解 如何记录行为数据 1. Kafka概述 1.产生原因 前端 传到日志 日志传到Flume 传到HADOOP 但是如果数据特比大&#xff0c;HADOOP就承受不住了 2.Kafka解决问题 控流消峰 Flume传给Kafka 存到Kafka Hadoop 从Kafka…...

Linux MQTT智能家居项目(智能家居界面布局)

文章目录 前言一、创建工程项目二、界面布局准备工作三、正式界面布局总结 前言 一、创建工程项目 1.选择工程名称和项目保存路径 2.选择QWidget 3.添加保存图片的资源文件&#xff1a; 在工程目录下添加Icon文件夹保存图片&#xff1a; 将文件放入目录中&#xff1a; …...

【Vue3】Vue3 UI 框架 | Element Plus —— 创建并优化表单

安装 # NPM $ npm install element-plus --save // 或者&#xff08;下载慢切换国内镜像&#xff09; $ npm install element-plus -S// 可以选择性安装 less npm install less less-loader -D // 可以选择性配置 自动联想src目录Element Plus 的引入和注入 main.ts import…...

如何基于 ACK Serverless 快速部署 AI 推理服务

作者&#xff1a;元毅 随着 AI 浪潮的到来&#xff0c;各种 AI 应用层出不穷&#xff0c;众所周知 AI 应用对 GPU 资源强烈依赖&#xff0c;但 GPU 很昂贵&#xff0c;如何降低 GPU 资源使用成本成为用户首要问题。而 AI 与 Serverless 技术结合&#xff0c;完全可以达到按需使…...

【奥义】如何用ChatGPT写论文搞模型

目录 你是否曾经在复现科研论文的结果时感到困难重重&#xff1f; 引言 1 打开需要复现的目标文献 2 提取公式定义的语句 3 文章公式、图实现 &#xff08;1&#xff09;用python复现目标文献中的公式 &#xff08;2&#xff09;用python复现目标文献中的图 4 Copy代码…...

欢迎光临,博客网站

欢迎光临&#xff1a;YUNYE博客~https://yunyeblog.com/更多的文章&#xff0c;供大家参考学习&#xff01;&#xff01;&#xff01;...

通过TightVNC远程访问MacOS

目录 一、下载 TightVNC 下载链接&#xff1a;https://www.tightvnc.com/ 下载后按步骤进行安装&#xff0c;安装完成后安装目录如下&#xff1a; 运行 tvnviewer.exe&#xff0c;输入远程 IP&#xff0c;点击【connect】&#xff1a; 输入密码&#xff0c;点击【OK】后即可远…...

智安网络|网络安全:危机下的创新与合作

随着信息技术的迅猛发展和互联网的普及&#xff0c;我们进入了一个高度网络化的社会。网络在提供便利和连接的同时&#xff0c;也带来了许多安全隐患和挑战。 一、网络安全的危险 **1.数据泄露和隐私侵犯&#xff1a;**网络上的个人和机构数据存在遭受泄露和盗取的风险&#…...

从系统角度,看智能制造|百世慧®

7月31日我们结束了智能制造专题第二期“电池智能制造质量管理应用及案例分享”的线上研讨会&#xff0c;有不少朋友没有来得及参加智能制造专题第一期研讨会&#xff0c;同时又工作繁忙。所以&#xff01;今天就由我百小能为大家快速讲解第一期研讨会——“电池智能制造应用”的…...

Dubbo 与 gRPC、Spring Cloud、Istio 的关系

很多开发者经常会问到 Apache Dubbo 与 Spring Cloud、gRPC 以及一些 Service Mesh 项目如 Istio 的关系&#xff0c;要解释清楚它们的关系并不困难&#xff0c;你只需要跟随这篇文章和 Dubbo 文档做一些更深入的了解&#xff0c;但总的来说&#xff0c;它们之间有些能力是重合…...

【uniapp 中使用uni-popup阻止左滑退出程序】

在uniapp中&#xff0c;可以使用uni-app插件uni-popup提供的阻止左滑退出程序的功能。具体步骤如下&#xff1a; 安装uni-popup插件&#xff1a;在HBuilderX编辑器中&#xff0c;打开manifest.json文件&#xff0c;找到“dependencies”字段&#xff0c;在其后添加&#xff1a…...

netty学习分享(一)

TCP与UDP TCP 是面向连接的、可靠的流协议&#xff0c;通过三次握手建立连接&#xff0c;通讯完成时要拆除连接。 UDP是面向无连接的通讯协议&#xff0c;UDP通讯时不需要接收方确认&#xff0c;属于不可靠的传输&#xff0c;可能会出现丢包现象 端口号&#xff1a; 端口号用…...

前端跨域问题解决方法

跨域是WEB浏览器专有的同源限制访问策略。(后台接口调用和postman等工具会出现) 跨源资源共享&#xff08;CORS&#xff0c;或通俗地译为跨域资源共享&#xff09;是一种基于 HTTP 头的机制&#xff0c;该机制通过允许服务器标示除了它自己以外的其他源&#xff08;域、协议或端…...

html基础面试题 html的元素居中的常用方法(基础知识温习)

html基础面试题 & html的元素居中的常用方法日常温习 1&#xff0c;使用text-align: center;属性&#xff1a; 对于内联元素&#xff08;如文本或图片&#xff09;&#xff0c;可以将其父元素的text-align属性设置为center。 <div style"text-align: center;&quo…...

VScode如何设置中文教程

前言&#xff1a;打开VSCode软件&#xff0c;可以看到刚刚安装的VSCode软件默认使用的是英文语言环境&#xff0c;但网上都是vscode中文界面教你怎么设置中文&#xff0c;可能不利于小白阅读&#xff0c;所以重装vscode&#xff0c;手摸手从英文变成中文。 设置为中文 打开VS…...

SpringCloud中 Sentinel 限流的使用

引入依赖 <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> </dependency>手动编写限流规则&#xff0c;缺点是不够灵活&#xff0c;如果需要改变限流规则需要修改源码…...

springboot文件上传和下载接口的简单思路

springboot文件上传和下载的简单思路 文件上传文件下载 文件上传 在springboot中&#xff0c;上传文件只需要在接口中通过 MultipartFile 对象来获取前端传递的数据&#xff0c;然后将数据存储&#xff0c;并且返回一个对外访问路径即可。一般对于上传文件的文件名&#xff0c…...

MySQL索引和事务

目录 索引的作用 与 概念 MySQL有哪几种索引类型 如何提高查找效率 聚簇索引与非聚簇索引 覆盖索引 索引的优点和缺点 索引的一些基本操作 索引优化 B树、B树、Hash、红黑树的区别 B树与B树的区别 MySQL为什么使用B树作为索引 联合索引中的顺序 MySQL的最左前缀原…...

typeScript 之 基础

工具: PlayGround 源码&#xff1a; GitHub TypeScript 变量声明 typeScript中变量声明注意&#xff1a; 开头不能以数字开头变量名称可以包含数字和字母除了下划线_和美元$符号外&#xff0c;不能包含其他任意特殊字符 声明的结构&#xff1a; let 变量名&#xff1a; 类型…...

【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密

在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...

均衡后的SNRSINR

本文主要摘自参考文献中的前两篇&#xff0c;相关文献中经常会出现MIMO检测后的SINR不过一直没有找到相关数学推到过程&#xff0c;其中文献[1]中给出了相关原理在此仅做记录。 1. 系统模型 复信道模型 n t n_t nt​ 根发送天线&#xff0c; n r n_r nr​ 根接收天线的 MIMO 系…...

深入浅出深度学习基础:从感知机到全连接神经网络的核心原理与应用

文章目录 前言一、感知机 (Perceptron)1.1 基础介绍1.1.1 感知机是什么&#xff1f;1.1.2 感知机的工作原理 1.2 感知机的简单应用&#xff1a;基本逻辑门1.2.1 逻辑与 (Logic AND)1.2.2 逻辑或 (Logic OR)1.2.3 逻辑与非 (Logic NAND) 1.3 感知机的实现1.3.1 简单实现 (基于阈…...

MySQL 8.0 事务全面讲解

以下是一个结合两次回答的 MySQL 8.0 事务全面讲解&#xff0c;涵盖了事务的核心概念、操作示例、失败回滚、隔离级别、事务性 DDL 和 XA 事务等内容&#xff0c;并修正了查看隔离级别的命令。 MySQL 8.0 事务全面讲解 一、事务的核心概念&#xff08;ACID&#xff09; 事务是…...

基于Springboot+Vue的办公管理系统

角色&#xff1a; 管理员、员工 技术&#xff1a; 后端: SpringBoot, Vue2, MySQL, Mybatis-Plus 前端: Vue2, Element-UI, Axios, Echarts, Vue-Router 核心功能&#xff1a; 该办公管理系统是一个综合性的企业内部管理平台&#xff0c;旨在提升企业运营效率和员工管理水…...

Rust 开发环境搭建

环境搭建 1、开发工具RustRover 或者vs code 2、Cygwin64 安装 https://cygwin.com/install.html 在工具终端执行&#xff1a; rustup toolchain install stable-x86_64-pc-windows-gnu rustup default stable-x86_64-pc-windows-gnu ​ 2、Hello World fn main() { println…...

Python常用模块:time、os、shutil与flask初探

一、Flask初探 & PyCharm终端配置 目的: 快速搭建小型Web服务器以提供数据。 工具: 第三方Web框架 Flask (需 pip install flask 安装)。 安装 Flask: 建议: 使用 PyCharm 内置的 Terminal (模拟命令行) 进行安装,避免频繁切换。 PyCharm Terminal 配置建议: 打开 Py…...

数据库正常,但后端收不到数据原因及解决

从代码和日志来看&#xff0c;后端SQL查询确实返回了数据&#xff0c;但最终user对象却为null。这表明查询结果没有正确映射到User对象上。 在前后端分离&#xff0c;并且ai辅助开发的时候&#xff0c;很容易出现前后端变量名不一致情况&#xff0c;还不报错&#xff0c;只是单…...

2.2.2 ASPICE的需求分析

ASPICE的需求分析是汽车软件开发过程中至关重要的一环&#xff0c;它涉及到对需求进行详细分析、验证和确认&#xff0c;以确保软件产品能够满足客户和用户的需求。在ASPICE中&#xff0c;需求分析的关键步骤包括&#xff1a; 需求细化&#xff1a;将从需求收集阶段获得的高层需…...

[特殊字符] Spring Boot底层原理深度解析与高级面试题精析

一、Spring Boot底层原理详解 Spring Boot的核心设计哲学是约定优于配置和自动装配&#xff0c;通过简化传统Spring应用的初始化和配置流程&#xff0c;显著提升开发效率。其底层原理可拆解为以下核心机制&#xff1a; 自动装配&#xff08;Auto-Configuration&#xff09; 核…...