利用QUEUE设计线程池

线程池的设计,一篇就够 文章目录为什么需要线程池条件变量结合互斥锁 + 任务队列eventfd + epolleventfd + epoll + 多队列的设计Lock-free 为什么需要线程池 在那些情况下我们会使用到多线程: 阻塞调用(阻塞IO调用、等待资源) 耗时的计算(读写文件、复杂的计算) 高密度任务(高并发低延时的网络IO请求) 面临以上情况时都去临时创建线程会带来什么问题: 创建了太多的线程,系统资源就会被... 阅读详情

在应用中,我们常常需要Thread缓冲池以提高程序的效率和并发性。本文演示了利用Queue这种数据结构实现一个简单的Thread缓冲池。

Thread缓冲池可以设计成以下这样:

缓冲池由几个工作Thread和一个Queue组成,Client负责把任务放到Queue里面(put方法),而工作Thread就依次取出这些任务并执行它们(get方法)。

Queue的一个经典实现是使用一个循环数组,如一个大小为size的数组,这个循环数组可以被想象成首尾相连的一个环。oldest指向Queue中最老的数据所在的位置,next指向下一个可以放新数据的位置。

放入一个新数据到next的位置后,需要更新next:next = (next + 1) % size;

从oldest位置取出一个数据后,需要更新oldest:oldest = (oldest + 1) % size;

当oldest == next的时候,Queue为空,

当(next + 1) % size == oldest的时候,Queue为满。

因为这个Queue会同时被多个线程访问,需要考虑在这种情况下Queue如何工作。首先,Queue需要是线程安全的,可以用Java里的synchronized关键字来确保同时只有一个Thread在访问Queue.

我们还可以注意到当Queue为空的时候,get操作是无法进行的;当Queue为满的时候,put操作又是无法进行的。在多线程访问遇到这种情况时,一般希望执行操作的线程可以等待(block)直到该操作可以进行下去。比如,但一个Thread在一个空Queue上执行get方法的时候,这个 Thread应当等待(block),直到另外的Thread执行该Queue的put方法后,再继续执行下去。在Java里面,Object对象的 wait(),notify()方法提供了这样的功能。

把上面的内容结合起来,就是一个SyncQueue的类:

public class SyncQueue {

public SyncQueue(int size) {

_array = new Object[size];

_size = size;

_oldest = 0;

_next = 0;

}

public synchronized void put(Object o) {

while (full()) {

try {

wait();

} catch (InterruptedException ex) {

throw new ExceptionAdapter(ex);

}

}

_array[_next] = o;

_next = (_next + 1) % _size;

notify();

}

public synchronized Object get() {

while (empty()) {

try {

wait();

} catch (InterruptedException ex) {

throw new ExceptionAdapter(ex);

}

}

Object ret = _array[_oldest];

_oldest = (_oldest + 1) % _size;

notify();

return ret;

}

protected boolean empty() {

return _next == _oldest;

}

protected boolean full() {

return (_next + 1) % _size == _oldest;

}

protected Object [] _array;

protected int _next;

protected int _oldest;

protected int _size;

}

可以注意一下get和put方法中while的使用,如果换成if是会有问题的。这是个很容易犯的错误。;-)

在以上代码中使用了ExceptionAdapter这个类,它的作用是把一个checked Exception包装成RuntimeException。详细的说明可以参考我的避免在Java中使用Checked Exception一文。

接下来我们需要一个对象来表现Thread缓冲池所要执行的任务。可以发现JDK中的Runnable interface非常合适这个角色。

最后,剩下工作线程的实现就很简单了:从SyncQueue里取出一个Runnable对象并执行它。

public class Worker implements Runnable {

public Worker(SyncQueue queue) {

_queue = queue;

}

public void run() {

while (true) {

Runnable task = (Runnable) _queue.get();

task.run();

}

}

protected SyncQueue _queue = null;

}

下面是一个使用这个Thread缓冲池的例子:

//构造Thread缓冲池

SyncQueue queue = new SyncQueue(10);

for (int i = 0; i < 5; i ++) {

new Thread(new Worker(queue)).start();

}

//使用Thread缓冲池

Runnable task = new MyTask();

queue.put(task);

为了使本文中的代码尽可能简单,这个Thread缓冲池的实现是一个基本的框架。当使用到实际中时,一些其他功能也可以在这一基础上添加,比如异常处理,动态调整缓冲池大小等等。

 

C++(23):实现一个通用的线程池 6.任务保存在tasks.emplace([task]() { (*task)();}这个lambda。3.submit的精髓是将函数和参数绑定后,完成其调用,就不再需要参数,因此就可以将其封入一个void()类型的lambda,这样就可以将这个统一形式的lambda保存到std::queue<std::function<void()>> tasks;2.submit函数用于向线程池派发任务,可以看到R是函数的返回类型,而task是将函数与参数绑定后的packaged_task对象。 阅读详情

相关推荐

SpawnPool缓冲池带实例Demo运用

SpawnPool缓冲池带实例Demo运用,unity包,导入后可以直接使用,修改好的,导入不会报错。

缓冲技术之二:缓冲池BufferPool的简单实现

在文章缓冲技术中提到无论是单缓冲、双缓冲或循环缓冲,均仅是进程专属缓冲配备,而一旦考虑到操作系统的分时并行特性,任一时刻只有一个进程的缓冲体系在工作之中,而其他进程的缓冲体系并不在工作(要么是迁移到swap cache外设磁盘上要么是占据物理内存,显著减少可用物理内存容量),所以采用公用缓冲池架构为多个并发进程提供缓冲服务是当前主流的手段(操作系统、数据库)。由于完整地提供操作系统级别的缓冲池涉及到

墨篙和小奶猫 7596

缓冲池实现

实现了一个循环缓冲队列,读线程从缓冲队列中读取数据,写线程向缓冲队列放入数据。可以运用在在网络文件传输或者本地文件复制。

C# 对象缓冲池模板类

在编程过程中,经常会遇到这种情况。有些对象需要从磁盘文件或数据库中读取数据,如果每次用过就将对象丢掉,下次再重新读磁盘,会影响程序的效率而且造成浪费。一个比较好的选择是使用缓冲池,下面的代码是我在编写股票程序时所写的一个缓冲池代码,因为考虑到会用的比较广泛,我花时间将它写成了通用的模板类。现在提供出来,如果有需要,你可以直接使用。 下面是缓冲池的代码: using System;

wuzhiqiang66的专栏 1099

Delphi实现的环形缓冲区(全文件)

Delphi实现的环形缓冲区,有详细的注释说明和示意图,请大家给提出更为高效,简单的改进意见。 添加可以自动扩展大小的功能

缓冲池的模拟(C++)

通过3个进程,3个缓冲队列,模拟缓冲池输入、计算、输出的过程。

网络数据处理缓冲区和缓冲池实现

在编写网络应用的时候数据缓冲区是应该比较常用的方式,主要用构建一个内存区用于存储发送的数据和接收的数据;为了更好的利用已有数据缓冲区所以构造一个缓冲池来存放相关数据方便不同连接更好地利用缓冲区,节省不停的构造新的缓冲区所带的损耗问题。 缓冲区 其实构造一个缓冲区非常简单,根据需分本相关大小的byte数组即可;既然是用于存放数据那就自然要实现读和写方法,看一下具体实现 p...

dcnna0422的博客 371

环形缓冲区实现类(RingBuffer)

环形缓冲区实现类(RingBuffer)

MySQL性能优化(三)Buffer Pool实现原理

本文主要介绍了缓冲池的数据结构、free链表、lush链表、lru链表

歪桃的博客 1万+

基于STM32的多普勒雷达测速

基于多普勒雷达传感器,以STM32单片机为主控芯片,根据不同模块检测距离的不同,使用不同多普勒雷达传感器实现对远近距离车辆行驶速度及方向的测量。 1、基础知识 无线电探测和测距,是用无线电(电磁波)方法发现目标并测定其空间位置的装置。随着雷达技术的发展,现代雷达不仅可以对目标进行定位,还可以测量目标的速度、对目标进行成像甚至测量目标的大小和材料特性。所有利用雷达波来检测物体速度的原理,其理论基础皆源自于“多普勒效应”,...

weixin_52801934的博客 6315

Keil5芯片包下载后无法识别?手把手排查教程

遇到Keil5芯片包下载后不被识别的问题别慌,常见原因包括安装路径错误或包未正确注册。通过检查Pack Installer状态和手动更新设备支持列表,轻松排查故障,确保开发环境正常运行。

weixin_35459464的博客 878

C#学习第28天:内存缓存和对象池化

C#针对内存优化的两种方式,缓存和对象池。

ghost143的博客 836

ARKit面部动画实战:如何用blend shape让数字人表情更自然(附中文对照表)

本文深入探讨了如何利用ARKit的blend shape技术驱动数字人面部动画,以实现更自然生动的表情。文章提供了详细的blend shape中文对照表,并分享了实战技巧,包括构建复合表情动画序列、处理不对称性与微表情,以及性能优化策略,旨在帮助开发者高效提升数字人的表情表现力。

weixin_29292535的博客 326

解绑过期订单(redisson延迟队列+线程池 )

当前的业务场景是号码绑定,请求参数中有个expiration过期时间,单位是秒,当绑定成功后,将订单信息存入redis,当前是用的redis的zset,score是当前时间戳加上expiration,然后起一个定时任务从queue中取订单,进行解绑。现在需要进行技术优化,打算将zset替换为redisson的RDelayedQueue。

qq_48079544的博客 340

python:numpy分享(保姆级教程)

创建数组:array和ndarray、rand()、randn()、arange()、randint()、uniform()astype()基础函数:ceil()、floor()、rint()、argmax()、argmin()、cumsum()、cumprod()numpy 是数据分析必不可少的第三方库,具有高性能的特点,多用于做数组分析。内置函数:ceil()、floor()、rint()主要用于数组计算,支持多维数组。array和ndarray。比较函数:all、any。去重函数:unique。

sulin123123的博客 1730

Python之achatbot包语法、参数和实际应用案例

本书是一本PyTorch深度学习实战指南,分为基础(前6章)和进阶(后5章)两大部分。基础部分涵盖张量运算、神经网络、数据预处理及CNN等核心内容;进阶部分则深入图像、文本、音频建模技术,重点解析Transformer架构及大语言模型开发。全书采用"理论+实践"模式,适合从零基础到进阶的PyTorch学习者。

王国平的博客 632

多线程爬取糗事网python3

1.导入模块: 使用到了多线程这里使用queue进行数据交互 2.创建爬取页面的类 3.创建处理数据的类 4.创建调用函数   CRAM_EXIT = False PARSE_EXIT = False def main(): pageQueue = Queue(20) for i in range(1, 21): pageQue...

qq_35723619的博客 380

断层错动和近断层地震动联合作用下软岩隧洞衬砌损伤分析

摘要 本文提出了一种基于Python的软岩隧洞衬砌损伤分析系统,重点研究断层错动和近断层地震动的联合作用效应。系统采用有限元方法建立隧洞-围岩体系模型,通过非线性动力分析评估衬砌结构损伤。研究内容包括:1)建立考虑应变软化的软岩本构模型;2)基于位错理论模拟断层错动过程;3)合成具有速度脉冲效应的近断层地震动;4)开发完整的动力响应分析流程。结果表明,所提出的方法能有效评估软岩隧洞在复杂地质条件下的抗震性能,为工程设计提供理论依据。 关键词:软岩隧洞、断层错动、近断层地震动、损伤分析、Python、有限元法

max500600的博客 842

Python 多线程任务调度系统设计

通过设置最大线程数,系统能够根据任务量动态调整资源,避免线程过多引发的竞争问题。通过try-except块捕获任务异常,并结合日志记录(如logging模块)追踪问题,可提升系统稳定性。主线程负责派发任务,工作线程从队列中获取任务并执行,确保任务有序高效完成。在当今高并发的应用场景中,高效的任务调度系统至关重要。本文将探讨如何设计一个基于Python的多线程任务调度系统,帮助开发者优化资源利用,提升程序性能。通过以上设计,Python多线程任务调度系统能够平衡性能与复杂度,适用于多种应用场景。

cjyeke_281的博客 192

【微电网优化】基于粒子群求解CHP机组、气网、电网、储热罐和电锅炉微电网优化模型附matlab代码

1 简介 我国风力发电近年发展迅速,装机容量已成为全球首位.随着风力发电在电力系统中的渗透率不断提高,我国多个地区(尤其是"三北"地区)已经面临着十分严峻的风电消纳问题,产生不容忽视的弃风问题.针对目前我国风电消纳存在的困难,本文提出粒子群优化CHP机组、气网、电网、储热罐和电锅炉微电网控制策略. 2 部分代码 Ppv=[0;0;0;0;0;0;9.86000000000000;19.0100000000000;33.1000000000000;45.0700000000000;64.7900000

qq_59747472的博客 672

unitree-G1外接 USB 麦克风完整配置指南

首先,将type-c麦克风插入G1机器人的USB口后,记录下USB麦克风的卡号(card)和设备号(device),通常显示为 card 1: Device [USB Audio Device]

m0_47999117的博客 599

【Linux】基于单例模式的线程池设计

【Linux】基于单例模式的线程池设计

tan_run的博客 2014

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

python系列——多线程之queue及线程池

参考博客: https://www.cnblogs.com/franknihao/p/6627857.html 1、作用 Queue用于建立和操作队列,常和threading类一起用来建立一个简单的线程队列。 2、种类 Queue.Queue(maxsize)  FIFO(先进先出队列)     Queue.LifoQueue(maxsize)  LIFO(先进后出队列)     Queue.PriorityQueue(maxsize)  为优先级越高的越先出来,对于一个队列中的所有元素组成的

有信念,才能走的更远 1937

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

线程池设计

这些必须都传给线程池中的线程才行,线程池中的线程从任务中拿取输入数据调用解决方法,最后把输出结果写入,线程池不需要对任务做任何多余的操作!而这个方法函数叫做——回调函数。大体思路是:任务队列不为空就通过条件变量向线程池中的线程发送信号执行任务,如果任务队列为空,则线程池中的线程在cond条件变量下等待。大体思路是: 把信号量的大小设置成任务队列task_queue的大小,这样临界资源的粒度就变小了,实现了生产和消费的解耦。最后线程池被设计成了单例模式,可以保证该线程池全局唯一。结构体中的对象包括👇。

潜心钻研技术 936

24并发设计模式——线程池模式

实际上线程池模式属于GoF一书23种设计模式的一种或多种设计模式组合。线程池的主要优点包括减少创建和销毁线程的开销、提高资源的利用率、简化线程管理。它适用于需要处理大量短时间任务的场景(如高并发)。在实际应用中,线程池模式有助于提高系统的响应速度和吞吐量,减少资源浪费,并使任务处理更为高效和可控。

qq_55610255的博客 1735

如何设计一个动态线程池?

动态线程池是一种能够在应用程序运行过程中实时调整其核心配置参数(如核心线程数、最大线程数等)而无需重启服务的线程池。它不仅支持动态修改线程池的参数,还通常内置了监控和告警功能,以帮助开发人员实时掌握线程池的状态。

玦尘的博客 2209
下一篇: JAVA线程注意事项
lanjun2005
博客等级 码龄21年 0粉丝 11原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值