线程池

十二、连接池线程池配置——线程池 如果需要在 Spring Boot 中创建自定义线程池(例如用于特定的任务或服务),可以使用。 阅读详情
最近脑袋有点犯贰。最近的工作总是涉及多线程,但网上的代码通用性不强。虽然windows已经内置了线程池,但是只能是VS2003以上的才能用,于是心一横就自己动手写了个线程池。
        该线程池可以在CONSOLE程序和GUI程序中都可用,如果想添加或者修改什么功能,可在源代码基础上进行。
        该线程池的包含了线程池和监视线程两个部分。线程池负责生成线程并响应外部的请求,监视线程负责监听外部线程请求,并从线程池获取可用的线程并执行。外部请求的工作函数必须符合unsigned workFunc(void* pvParam)形式,至于函数名可随意指定。工作函数可以是相同的函数也可以是不同的功能函数,这里就实现了功能定制。
        使用线程池之前,首先初始化线程池并指定线程池的容量大小,指定的容量大小不能大于线程池的最大容量。线程池默认容量大小为10,为了达到最好的性能和效率,建议使用者将线程池的容量设定为计算机CPU个数的2倍(这是一条经验规则)。
        初始化完成后可以向线程池添加工作函数,请遵循工作函数的原型规则。此时监视线程会向线程池请求一个可用的线程,如果线程请求已满,监视线程会循环检查可用的线程,如果得到一个可用的线程,将执行该工作函数。
        该线程池已经过本人的详细测试,如果还出现了问题请回复或者自行解决。

下面贴出线程池源代码和一个使用用例。

线程池头文件:

// CThreadPool.h: interface for the CThreadPool class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_CTHREADPOOL_H__8015A6DC_2CCD_4436_AD0F_4F5178B69DA4__INCLUDED_)
#define AFX_CTHREADPOOL_H__8015A6DC_2CCD_4436_AD0F_4F5178B69DA4__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <afx.h>
#include <process.h>

typedef unsigned (/*__stdcall*/ *PWORKPROC)(void* pvParam);

typedef struct _Thread
{
	PWORKPROC	pWorkFunc;
	void*		pvParam;
}Thread;

typedef struct _threadInfo
{
	BOOL	bValid;
	UINT	uiParamLen;
	UINT	uiThreadId;
	UINT	uiThreadIndex;
	Thread	thread;
	HANDLE  hThread;
	HANDLE  hEvent;
}ThreadInfo;

#define MAX_CAPACITY 20		//

class CThreadPool  
{
public:
	CThreadPool();
	CThreadPool(UINT uiMaxCapacity);
	void IncreaseThreadCount();
	int  GetRequestCount();
	void DescendThreadCount();
	void ResetThreadInfo(UINT uiIndex);
	UINT GetValidThread(void);
	UINT GetMaxCapacity(void);
	UINT GetCurrentCount();
	void AddWorkItem(PWORKPROC workFunc, void* pvParam);
	UINT GetCapacity(void);
	int  InitThreadPool(UINT uiCapacity=8);
	virtual void DisplayAllThreadInfo(void);
	Thread* GetThreads();
	ThreadInfo* GetThreadInfo();
	static CThreadPool* GetCurrentPool(void);
	virtual ~CThreadPool();

private:
	static CThreadPool* m_poCurrentPool;
	ThreadInfo* m_pThreadInfo;
	int  m_iReqCount;
	UINT m_uiCurrentCount;
	UINT m_uiMaxCapacity;
	UINT m_uiPoolCapacity;
	Thread* m_pThreads;
};

#endif // !defined(AFX_CTHREADPOOL_H__8015A6DC_2CCD_4436_AD0F_4F5178B69DA4__INCLUDED_)


线程池源文件:

// CThreadPool.cpp: implementation of the CThreadPool class.
//
//////////////////////////////////////////////////////////////////////

#include "CThreadPool.h"

CThreadPool* CThreadPool::m_poCurrentPool=NULL;
unsigned __stdcall ThreadProc(void* pvParam);
unsigned __stdcall ListenThread(void* pvParam);
HANDLE hListenThread=NULL;


//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CThreadPool::CThreadPool()
{
	m_uiMaxCapacity=MAX_CAPACITY;
	m_poCurrentPool=this;
}

CThreadPool::CThreadPool(UINT uiMaxCapacity)
{
	m_uiMaxCapacity=uiMaxCapacity;	
	m_poCurrentPool=this;
}
CThreadPool::~CThreadPool()
{
	if (m_pThreadInfo!=NULL)
	{
		delete (m_pThreadInfo);
		m_pThreadInfo=NULL;
	}
	if (m_pThreads!=NULL)
	{
		delete (m_pThreads);
		m_pThreads=NULL;
	}

	for (UINT loop=0;loop<m_uiPoolCapacity;loop++)
	{
		CloseHandle(m_pThreadInfo[loop].hThread);
		CloseHandle(m_pThreadInfo[loop].hEvent);
	}

	CloseHandle(hListenThread);
}

int CThreadPool::InitThreadPool(UINT uiCapacity)
{
	HANDLE hThread=NULL;
	HANDLE hEvent=NULL;
	UINT   uiThreadId=0;
	UINT   loop=0;
	
	m_pThreadInfo=NULL;
	m_uiCurrentCount=0;
	m_iReqCount=0;

	if (uiCapacity>m_uiMaxCapacity)
	{
		return -1;
	}

	m_uiPoolCapacity=uiCapacity;
	m_pThreadInfo=new ThreadInfo[uiCapacity];
	m_pThreads=new Thread[MAX_CAPACITY];
	for (;loop<MAX_CAPACITY;loop++)
	{
		m_pThreads[loop].pvParam=NULL;
		m_pThreads[loop].pWorkFunc=NULL;
	}
	
	for (loop=0;loop<m_uiPoolCapacity;loop++)
	{
		m_pThreadInfo[loop].bValid=TRUE;
		m_pThreadInfo[loop].thread.pWorkFunc=NULL;
		m_pThreadInfo[loop].thread.pvParam=NULL;
		m_pThreadInfo[loop].uiParamLen=0;//
		m_pThreadInfo[loop].uiThreadIndex=loop;
		m_pThreadInfo[loop].hThread=NULL;
		m_pThreadInfo[loop].hEvent=NULL;

		hEvent=CreateEvent(NULL,FALSE,FALSE,NULL);
		if (hEvent==NULL)
		{
			return -2;
		}
		m_pThreadInfo[loop].hEvent=hEvent;

		hThread=(HANDLE)_beginthreadex(NULL,0,ThreadProc,(void*)(&m_pThreadInfo[loop].uiThreadIndex),0,&uiThreadId);//
		if (hThread==NULL)
		{
			return -3;
		}
		
		m_pThreadInfo[loop].uiThreadId=uiThreadId;
		m_pThreadInfo[loop].hThread=hThread;
	}

	hListenThread=(HANDLE)_beginthreadex(NULL,0,ListenThread,NULL,0,NULL);//
	if (hListenThread==NULL)
	{
		return -4;
	}

	return 0;
}

unsigned __stdcall ThreadProc(void* pvParam)
{
	CThreadPool* threadPool=NULL;
	ThreadInfo*  threadInfo=NULL;
	PWORKPROC workProc=NULL;
	void*     workParam=NULL;
	UINT	uiIndex=0;
	
	uiIndex=*(int*)pvParam;
	threadPool=CThreadPool::GetCurrentPool();
	threadInfo=threadPool->GetThreadInfo();
	
	while(TRUE)
	{
		if (WaitForSingleObject(threadInfo[uiIndex].hEvent,INFINITE)!=WAIT_OBJECT_0)
		{
			continue ;
		}
		
		workProc=NULL;
		workParam=NULL;
		
		//printf("Execute thread:index=%d\thandle=%p\n", uiIndex,threadInfo[uiIndex].hThread);//
		workProc=threadInfo[uiIndex].thread.pWorkFunc;
		workParam=threadInfo[uiIndex].thread.pvParam;
		if (workProc!=NULL)
		{
			workProc(workParam);
		}
		
		threadPool->ResetThreadInfo(uiIndex);
		threadPool->DescendThreadCount();
	}
	return 0;
}

void CThreadPool::AddWorkItem(PWORKPROC workFunc, void *pvParam)
{
	m_pThreads[m_iReqCount%MAX_CAPACITY].pWorkFunc=workFunc;
	m_pThreads[m_iReqCount%MAX_CAPACITY].pvParam=pvParam;

	m_iReqCount++;
}

unsigned __stdcall ListenThread(void* pvParam)
{
	CThreadPool* threadPool=NULL;
	ThreadInfo*  threadInfo=NULL;
	Thread*		 threads=NULL;
	PWORKPROC workProc=NULL;
	void*     workParam=NULL;
	int     iReqCount=0;
	int		uiIndex=0;
	
	threadPool=CThreadPool::GetCurrentPool();
	threadInfo=threadPool->GetThreadInfo();	
	threads=threadPool->GetThreads();
	while(TRUE)
	{
		while(iReqCount!=threadPool->GetRequestCount())
		{
			workProc=NULL;
			workParam=NULL;

			uiIndex=threadPool->GetValidThread();
			//线程池请求已满,此处循环等待可用的线程
			if (uiIndex<0)
			{
				continue ;
			}

			//printf("Request thread index:%d\n", uiIndex);
			threadPool->IncreaseThreadCount();

			
			workProc=threads[iReqCount%MAX_CAPACITY].pWorkFunc;
			workParam=threads[iReqCount%MAX_CAPACITY].pvParam;
			
			threadInfo[uiIndex].bValid=FALSE;
			threadInfo[uiIndex].thread.pvParam=workParam;
			threadInfo[uiIndex].thread.pWorkFunc=workProc;
			threadInfo[uiIndex].uiParamLen=0;//

			SetEvent(threadInfo[uiIndex].hEvent);
			iReqCount++;
		}
	}
	return 0;
}
void CThreadPool::DisplayAllThreadInfo()
{
	//printf("Display all information of thread.\n");
	
	for (UINT loop=0;loop<GetCapacity();loop++)
	{
		//printf("\tIndex:%d\tHandle:%p\tThreadId:%d\n", m_pThreadInfo[loop].uiThreadIndex,m_pThreadInfo[loop].hThread,m_pThreadInfo[loop].uiThreadId);
	}
	//printf("\n");
	
}

void CThreadPool::ResetThreadInfo(UINT uiIndex)
{	
	m_pThreadInfo[uiIndex].bValid=TRUE;
	m_pThreadInfo[uiIndex].uiParamLen=0;//
	m_pThreadInfo[uiIndex].thread.pvParam=NULL;
	m_pThreadInfo[uiIndex].thread.pWorkFunc=NULL;
}

UINT CThreadPool::GetValidThread()
{
	for (UINT loop=0;loop<GetCapacity();loop++)
	{
		if (m_pThreadInfo[loop].bValid==TRUE)
		{
			return m_pThreadInfo[loop].uiThreadIndex;
		}
	}

	return -1;
}

UINT CThreadPool::GetCapacity()
{
	return m_uiPoolCapacity;
}
CThreadPool* CThreadPool::GetCurrentPool()
{
	return m_poCurrentPool;
}
UINT CThreadPool::GetCurrentCount()
{
	return m_uiCurrentCount;
}
UINT CThreadPool::GetMaxCapacity()
{
	return m_uiMaxCapacity;
}
ThreadInfo* CThreadPool::GetThreadInfo()
{
	return m_pThreadInfo;
}
void CThreadPool::DescendThreadCount()
{
	--m_uiCurrentCount;
}
int CThreadPool::GetRequestCount()
{
	return m_iReqCount;
}
void CThreadPool::IncreaseThreadCount()
{
	m_uiCurrentCount++;
}
Thread* CThreadPool::GetThreads()
{
	return m_pThreads;
}

一个使用用例:

#include "CThreadPool.h"

unsigned Test(void* param)
{
	printf("TEST%s for multiple threads.\n", (char*)param);
	return 0;
}

int main(int argc, char* argv[])
{
	CThreadPool pool;
	int iRet=0;
	
	iRet=pool.InitThreadPool(4);
	if (iRet<0)
	{
		printf("Initial thread pool;iRet=%d\n",iRet);
		return EXIT_FAILURE;
	}
	
	pool.DisplayAllThreadInfo();

	pool.AddWorkItem(Test,"0");
	//Sleep(1000);
	pool.AddWorkItem(Test,"1");
	//Sleep(1000);
	pool.AddWorkItem(Test,"2");	
	//Sleep(1000);
	pool.AddWorkItem(Test,"3");
	//Sleep(1000);
	pool.AddWorkItem(Test,"4");

	WaitMessage(); //此处不可少
	return EXIT_SUCCESS;
}

线程池详解:线程池七大核心参数、线程池工作原理、线程池的创建方式、线程池的拒绝策略、如何合理分配线程池大小 线程池是一种用于管理和复用线程的机制,它允许我们在需要执行一些并发任务时,可以重复使用已经创建好的线程,而不是每次都创建新的线程。这样可以减少线程创建和销毁的开销,提高系统的性能和响应速度。并发线程池的优点包括: 提高系统的性能和吞吐量,因为可以重复使用已经创建好的线程,减少线程创建和销毁的开销。 可以控制并发任务的执行顺序和数量,从而避免系统资源被过度占用。 可以设置线程池的参数,如核心线程数、最大线程数、任务队列等,以满足不同场景的需求。 阅读详情

相关推荐

AI+AB测试提升电商主图点击率实战指南

在电商运营中,主图点击率(CTR)是衡量商品吸引力的核心指标,直接影响转化率和订单增长。通过AI技术批量生成高质量主图素材,结合数据驱动的AB测试方法,可以显著提升点击率。AI工具如MidJourney和Stable Diffusion能够快速生成多样化视觉方案,而自动化处理流水线则确保素材规格统一。AB测试体系通过多维变量控制和流量分配策略,科学验证不同素材效果。这种方法特别适用于需要快速迭代的电商场景,某女装店铺案例显示CTR从1.2%提升至3.8%,验证了AI+数据协同优化的技术价值。

weixin_29058331的博客 299

奇怪的PVOID参数--SystemParametersInfo的使用

PVOID SystemParametersInfo

jiaodou2的博客 742

归因分析计算因子贡献度常见的方法

在归因分析中,我们一般都需要计算出每个因子的贡献度是多少,比如产品DAU上升,对年龄段维度进行拆解,看是不同年龄段的用户对DAU上升的贡献度是多少,一般根据指标的类型,计算贡献度的方法也不一样,下面就列出一些常见的归因分析贡献度的计算方法。

Hubans的博客 4万+

线程基础知识

一、进程由两部分组成,一个是进程内核对象,另一个是地址空间。同样线程也是由两部分组成的:一个是线程的内核对象,另一个是线程堆栈。二、线程的进入点函数每个线程必须拥有一个进入点函数,线程从这个进入点开始运行。主线程的进入点函数:即main、wmain、WinMain或wWinMain。辅助线程的进入点函数的原型:    DWORD WINAPI ThreadFunc(PVOID pvPa

qzh的专栏 460

DGX Spark上PyTorch GPU环境配置实战:CUDA 13.0与ARM架构全流程

在深度学习中,CUDA作为GPU加速计算的底层基础,其版本与深度学习框架(如PyTorch)的匹配直接影响模型训练的效率与稳定性。GPU环境配置不仅涉及驱动、CUDA工具链与框架运行时的协同,还依赖于硬件架构与预构建包的兼容性。在AI开发机Ubuntu系统上,正确对齐CUDA版本、计算能力架构及安装源,是避免环境故障、发挥硬件算力的关键。无论是面向个人AI超算还是通用GPU服务器,掌握版本对齐、路径隔离与验证方法,都能大幅提升开发效率。本文以DGX Spark为例,详解从环境摸底到PyTorch GPU版本

weixin_29483277的博客 222

数据分析——员工离职预测

员工离职预测一. 题目描述二. 数据说明三. 步骤实现1.导入并查看2.数据探索性分析3.数据处理4.模型分析5.结果分析(1) 可视化的结果分析(2)特征选择结果分析(3)多模型交叉验证结果分析 一. 题目描述 员工是否准备离职是困扰用人单位的问题,其关系到单位业务的开展及新人员的招聘,及时的分析出有离职倾向的员工成为关键的因素。数据主要包括影响员工离职的各种因素(工资、出差、工作环境满意度、工作投入度、是否加班、是否升职、工资提升比例等)以及员工是否已经离职的对应记录。 二. 数据说明 数据分为训练数据

weixin_43925467的博客 1万+

C# params 用法简介

params 是C#的关键字, 可变长参数,是在声明方法时参数类型或者个数不确定时使用 关于params 参数数组,需掌握以下几点: 一.参数数组必须是一维数组 二.不允许将params修饰符与ref和out修饰符组合起来使用 三.与参数数组对应的实参可以是同一类型的数组名,也可以是任意多个与该数组的元素属于同一类型的变量 四.若实参是数组则按引用传递,若实参是变量或表达式则按值传递 五.形式为:方法修饰符 返回类型 方法名(params 类型[ ] 变量名) 例:private void Test( pa

qq_43121342的博客 330

maxwell与steady state thermal 通过workbench耦合仿真

文章目录maxwellsteady state thermal maxwell 1加入maxwell并打开 2导入模型 3选择求解器类型:涡流求解器eddy current 4修改模型名字不能带_等特殊符号 5为模型赋材料 6设立3D边界,各边电流进出方向为0其余方向300 7设置激励条件,可设置电流大小,相位,方向 8设置集肤深度,选取中间铜导体的体然后设置,如何设置看帮助文档 9求解设置 迭代步数 收敛精度 交流电频率 10验证条件满足计算 11求解 发现无法求解,删除ai

roymustang的博客 9202

关于void *para的传递

typedef struct params { cv::Point loc1[MAX_OBJECTS]; cv::Point loc2[MAX_OBJECTS]; cv::Mat objects[MAX_OBJECTS]; char* win_name; cv::Mat orig_img; cv::Mat cur_img; int n; } params; 如果 params

fanjiaxia的专栏 1187

别再手动配电脑了!手把手教你用Windows Server 2022搭建企业AD域(附DNS配置避坑指南)

本文详细介绍了如何使用Windows Server 2022搭建企业AD域,提升20+终端的管理效率。通过实战案例和避坑指南,解析AD域的核心价值、部署步骤及DNS配置技巧,帮助企业实现集中权限管理、安全策略统一部署,显著降低IT运维成本。

weixin_30652897的博客 352

【数字图像相关-OpenCorr学习笔记】Epipolar search原理+代码解析

OpenCorr是一个开源C++库,用于研究和开发数字图像相关(DIC)技术它提供了2D和立体声DIC的全功能模块,以及数字体积相关(DVC)。最近正在学习OpenCorr,为了更深层次地理解ICGN,我打算浅浅剖析Opencorr的代码,学习的过程中写下这篇学习笔记,以后忘记了还能回来看看。同时,作为一名在读研究生,希望能得到社区大佬的指点,以及跟同学们一起学习进步。这一期主要讲解Eipipolar search的原理,并且附上部分代码解析。

ywyywyy的博客 1359

【C进阶】同事用void把我给秀翻了!

上面这些函数都是与内存操作有关的函数,可能一些小伙伴使用过也不一定知道每个参数的具体类型是什么,这些void*部分的形参所传入的实参都是不需要进行强制类型转化的,所以根本就不需要关注传入指针所指向的具体类型,然而函数所返回的void。虽然void不能直接修饰变量,但是其可以用于修饰指针的指向即无类型指针void*,无类型指针那就有意义了,无类型指针不是一定要指向无类型数据,而是可以指向任意类型的数据。然而我们平时所定义的变量都会有具体的类型,int,float,char等等,那是否有void类型的变量呢?

qq_41854911的博客 926

芒果YOLOv7改进04:Loss篇:原创改进损失函数Repulsion:独家首发最新改进Repulsion Loss解决目标遮挡场景下检测,为解决密集人群检测中遮挡设计的损失函数,打造高效检测器涨点

YOLOv7原创改进Repulsion|首发最新改进为解决密集人群检测中遮挡设计的损失函数

包括YOLOv5、YOLOv7、YOLOv8等模型改进 3254

线程池怎么调优?线程池的几种方式?及线程池的实战

线程池的调优

weixin_60153382的博客 2702

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

35.Java线程池(线程池概述、线程池的架构、线程池的种类与创建、线程池的底层原理、线程池的工作流程、线程池的拒绝策略、自定义线程池)

35.Java线程池(线程池概述、线程池的架构、线程池的种类与创建、线程池的底层原理、线程池的工作流程、线程池的拒绝策略、自定义线程池)

weixin_52173250的博客 1763

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

spring 的线程池还是 java 的线程池

Java 提供了一个强大的并发库,其中包含了线程池的基本实现。线程池是接口的实现类,用于管理线程的创建、执行和终止。通过线程池,开发者可以避免频繁创建和销毁线程带来的开销,从而提升应用程序的性能。Spring 框架对 Java 的并发库进行了封装,使得线程池的配置更加简洁和灵活。Spring 提供了接口,这是对 JavaExecutor接口的扩展,允许开发者更容易地配置和管理线程池。Spring 的线程池配置通常通过 XML 或 Java 配置类来实现,并且 Spring 提供了多种实现,如等。

Flying_Fish_roe的博客 1675

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

线程池——线程池

本文主要讲线程池:1)线程池的引入;2)Java标准库中的线程池;3)ThreadPoolExecutor 构造方法和拒绝策略;4)实现一个简单的线程池

2301_76937176的博客 1167

线程池、及Springboot线程池实践

线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务。

jainszhang的博客 1723

线程池讲解

/核心线程池大小//最大线程数//队列容量//活跃时间//线程名字前缀使用}, iAlgoFilter.getType() + "-----计算").start();}*/@Overridelog.info("当前线程:{},执行特征编号:{}的:{} 计算", Thread.currentThread().getName(),code, iAlgoFilter.getType());});

cf的博客 1664

线程池详解,生命周期,线程池种类,预热

线程池详解,生命周期,线程池种类,预热

hello world 1315

什么是线程池,线程池的概念、优点、缺点,如何使用线程池,最大线程池怎么定义?

什么是线程池,线程池的概念、优点、缺点,如何使用线程池

Li2992673708的博客 3100

Java 线程池

在实际使用中,线程是很占用系统资源的,如果对线程管理不善很容易导致系统问题。(1)线程池中最多执行1个线程,之后提交的线程活动将会排在队列中依次执行。(1)线程池中最多执行1个线程,之后提交的线程活动将会排在队列中依次执行。(2)线程池中的线程可进行缓存重复利用和回收。(1)线程池中的线程处于一定的量,可以很好的控制线程的并发量。(2)线程可以重复被使用,在显式关闭之前,都将一直存在。(1)线程池中具有指定数量的线程,即便是空线程也将保留。(3)当线程池中,没有可用线程,会重新创建一个线程。

ggfgfggg的博客 1065

JUC线程池和spring线程池

简介:目前常用的线程池有两种,一种是jdk自带的ThreadPoolExecutor来创建线程池,另一种是spring框架中的ThreadPoolTaskExecutor来创建线程池。 JDK自带的线程池 (1)线程池执行过程入下图: (2)常用的线程池 使用Executors创建线程池:这是jdk自带的创建线程池的方法。通过Exceutors创建线程池,常见的线程池有四种: Executors.newFixedThreadPool(int nThreads):固定长度的线程池...

qq_27661881的博客 1802

线程池总结

线程数的设置主要取决于业务是属于 IO 密集型还是 CPU 密集型。对于 CPU 密集型任务,其主要工作是进行大量的计算,且较少出现导致线程阻塞的情况。在这种场景下,一般将线程数设置为 CPU 核心数 + 1。例如,如果服务器拥有 8 个 CPU 核心,那么适宜将线程数设定为 9。如此一来,能够充分利用 CPU 资源,同时避免因过多线程切换而产生的额外开销。对于 IO 密集型任务,执行过程中需要大量的 I/O 操作,如磁盘 I/O、网络 I/O 等,这可能导致大量的线程阻塞。

Brenda_Bestow的博客 1152

【线程池】Tomcat线程池

最近看到篇关于 Tomcat 线程池的博客,因为之前只看过 JDK 线程池,记录一下。在微服务横行的今天,确实还是有必要研究研究 Tomcat 的线程池Tomcat 线程池和 JDK 线程池最大的不同就是它先把最大线程数用完,然后再提交任务到队列里面。深入理解线程池(ThreadPoolExecutor)——细致入微的讲源码。workerstarted = true-优快云博客本文主要介绍了 Tomcat 线程池的运行流程,和 JDK 线程池的流程比起来,它确实不一样。

m0_64944491的博客 1724

线程池的使用

线程池是一种并发处理机制,它预先创建并维护一定数量的工作线程,在接收到任务时,从线程池中分配一个线程去执行,任务完成后线程并不会立即结束,而是返回到线程池中等待下一次任务。这种设计可以避免频繁地创建和销毁线程,提高系统性能,降低资源消耗,并且能够更好地管理线程间的协作。

Z_DOUBLE_Y的博客 1769
上一篇: Java几种建立实例的方法
下一篇: Linux笔记
Yanortun
博客等级 码龄17年 0粉丝 4原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值