一、 线程池的原理:
线程池,究竟是怎么一回事?其实线程池的原理很简单,类似于操作系统中的缓冲区的概念,它的流程如下:
先启动若干数量的线程,并让这些线程都处于睡眠状态,当客户端有一个新请求时,就会唤醒线程池中的某一个睡眠线程,让它来处理客户端的这个请求,当处理完这个请求后,线程又处于睡眠状态。
可能你也许会问:为什么要搞得这么麻烦,如果每当客户端有新的请求时,我就创建一个新的线程不就完了?这也许是个不错的方法,因为它能使得你编写代码相对容易一些,但你却忽略了一个重要的问题——性能!
就拿我所在的单位来说,我的单位是一个省级数据大集中的银行网络中心,高峰期每秒的客户端请求并发数超过100,如果为每个客户端请求创建一个新线程的话,那耗费的CPU时间和内存将是惊人的,如果采用一个拥有200个线程的线程池,那将会节约大量的的系统资源,使得更多的CPU时间和内存用来处理实际的商业应用,而不是频繁的线程创建与销毁。
二、 linux线程池的C语言实现
通常我们使用多线程的方式是,需要时创建一个新的线程,在这个新的线程里执行特定的任务,然后在任务完成后退出。这在一般的应用里已经能够满足我们应用的需要,毕竟我们并不是什么时候都需要创建大量的线程,并在它们执行一个简单的任务后销毁。
但是在一些web、email、database等应用里,比如彩铃,我们的应用在任何时候都要准备应对数目巨大的连接请求,同时,这些请求所要完成的任务却又可能非常的简单,即只占用很少的处理时间。这时,我们的应用有可能处于不停的创建线程并销毁线程的状态。虽说比起进程的创建,线程的创建时间已经大大缩短,但是如果需要频繁的创建线程,并且每个线程所占用的处理时间又非常简短,则线程创建和销毁带给处理器的额外负担也是很可观的。
线程池的作用正是在这种情况下有效的降低频繁创建销毁线程所带来的额外开销。一般来说,线程池都是采用预创建的技术,在应用启动之初便预先创建一定数目的线程。应用在运行的过程中,需要时可以从这些线程所组成的线程池里申请分配一个空闲的线程,来执行一定的任务,任务完成后,并不是将线程销毁,而是将它返还给线程池,由线程池自行管理。如果线程池中预先分配的线程已经全部分配完毕,但此时又有新的任务请求,则线程池会动态的创建新的线程去适应这个请求。当然,有可能,某些时段应用并不需要执行很多的任务,导致了线程池中的线程大多处于空闲的状态,为了节省系统资源,线程池就需要动态的销毁其中的一部分空闲线程。因此,线程池都需要一个管理者,按照一定的要求去动态的维护其中线程的数目。
基于上面的技术,线程池将频繁创建和销毁线程所带来的开销分摊到了每个具体执行的任务上,执行的次数越多,则分摊到每个任务上的开销就越小。
当然,如果线程创建销毁所带来的开销与线程执行任务的开销相比微不足道,可以忽略不计,则线程池并没有使用的必要。比如,FTP、Telnet等应用时。
现在已经可以从网上找到一些线程池的实例,但它们一般都是使用C++、Java等语言实现的,如果我们使用C实现我们的应用的话,使用起来就会遇到麻烦。基于此,利用上面的框架,我使用C实现了一个简单的线程池库,代码可以从sourceforge下载。
为了使这个线程池库使用起来更加方便,我在C实现中加入了一些OO的思想,与Objective-C不同,它仅仅是使用struct模拟了C++中的类,在linux的源代码和一些应用,比如xine里,我们可以看到这种使用方式。
在这个库里,与用户有关的接口主要有:
typedef struct tp_work_desc_s tp_work_desc;
typedef struct tp_work_s tp_work;
typedef struct tp_thread_info_s tp_thread_info;
typedef struct tp_thread_pool_s tp_thread_pool;
//thread parm
struct tp_work_desc_s{
……
};
//base thread struct
struct tp_work_s{
//main process function. user interface
void (*process_job)(tp_work *this, tp_work_desc *job);
};
tp_thread_pool *creat_thread_pool(int min_num, int max_num);
tp_work_desc_s表示应用线程执行任务时所需要的一些信息,会被当作线程的参数传递给每个线程,依据应用的不同而不同,需要用户定义结构的内容。tp_work_s就是我们希望线程执行的任务了。当我们申请分配一个新的线程时,首先要明确的指定这两个结构,即该线程完成什么任务,并且完成这个任务需要哪些额外的信息。接口函数creat_thread_pool用来创建一个线程池的实例,使用时需要指定该线程池实例所能容纳的最小线程数min_num和最大线程数max_num。最小线程数即线程池创建时预创建的线程数目,这个数目的大小也直接影响了线程池所能起到的效果,如果指定的太小,线程池中预创建的线程很快就将分配完毕并需要创建新的线程来适应不断的请求,如果指定的太大,则将可能会有大量的空闲线程。我们需要根据自己应用的实际需要进行指定。描述线程池的结构如下:
//main thread pool struct
struct tp_thread_pool_s{
TPBOOL (*init)(tp_thread_pool *this);
void (*close)(tp_thread_pool *this);
void (*process_job)(tp_thread_pool *this, tp_work *worker, tp_work_desc *job);
int (*get_thread_by_id)(tp_thread_pool *this, int id);
TPBOOL (*add_thread)(tp_thread_pool *this);
TPBOOL (*delete_thread)(tp_thread_pool *this);
int (*get_tp_status)(tp_thread_pool *this);
int min_th_num; //min thread number in the pool
int cur_th_num; //current thread number in the pool
int max_th_num; //max thread number in the pool
pthread_mutex_t tp_lock;
pthread_t manage_thread_id; //manage thread id num
tp_thread_info *thread_info; //work thread relative thread info
};
结构tp_thread_info_s描述了各个线程id、是否空闲、执行的任务等信息,用户并不需要关心它。
//thread info
struct tp_thread_info_s{
pthread_t thread_id; //thread id num
TPBOOL is_busy; //thread status:true-busy;flase-idle
pthread_cond_t thread_cond;
pthread_mutex_t thread_lock;
tp_work *th_work;
tp_work_desc *th_job;
};
tp_thread_pool_s结构包含了有关线程池操作的接口和变量。在使用creat_thread_pool返回一个线程池实例之后,首先要使用明确使用init接口对它进行初始化。在这个初始化过程中,线程池会预创建指定的最小线程数目的线程,它们都处于阻塞状态,并不损耗CPU,但是会占用一定的内存空间。同时init也会创建一个线程池的管理线程,这个线程会在线程池的运行周期内一直执行,它将定时的查看分析线程池的状态,如果线程池中空闲的线程过多,它会删除部分空闲的线程,当然它并不会使所有线程的数目小于指定的最小线程数。
在已经创建并初始化了线程池之后,我们就可以指定tp_work_desc_s和tp_work_s结构,并使用线程池的process_job接口来执行它们。这些就是我们使用这个线程池时所需要了解的所有东西。如果不再需要线程池,可以使用close接口销毁它。
线程池的创建如果是在方法里,必须要关闭的。
相关推荐
线程池管理是多线程编程中的一个重要概念,它是一种高效、可管理的并发执行机制。在计算机程序中,线程池是由多个工作线程组成的集合,这些线程预先创建并处于待命状态,等待执行任务。通过使用线程池,开发者可以...
通过以上代码示例和注意事项,你可以更好地理解和应用Android中的线程池管理,提高应用的并发处理能力和响应速度。在实际项目中,结合具体业务需求,灵活运用ThreadPoolExecutor和ScheduledExecutorService,将有助...
线程池是Java多线程编程中的重要概念,它的出现是为了...总之,线程池管理源码的学习有助于开发者深入理解Java并发编程,从而设计出更健壮、高效的系统。对于大型应用,正确配置和使用线程池是提升系统并发性能的关键。
线程池管理和多线程上传是并发编程中的一个重要实践,特别是在大数据传输和网络服务中。在Java等编程语言中,线程池通过有效地管理和复用线程资源,避免了频繁创建和销毁线程带来的开销,提升了系统性能。下面将详细...
在"完成演示线程池管理者"部分,可能包含了一个自定义的线程池管理器,它可能扩展了`ExecutorService`或`ThreadPoolExecutor`,并添加了监控、调整线程池参数、任务调度等功能。这样的管理器可以帮助我们更好地控制...
# 基于C++的线程池管理系统 ## 项目简介 本项目是一个基于C++实现的线程池管理系统,旨在提供高效、灵活的多线程任务管理功能。通过多种工作模式和任务优先级管理,项目能够适应不同的任务负载需求,并确保任务的...
### 基于反馈的自适应线程池管理框架 #### 概述 本文献介绍了一种名为**基于反馈的自适应线程池管理框架**(FFATpM)的新颖方法,旨在解决传统线程池调度管理中存在的问题,特别是在面对应用需求和计算资源动态变化...
# 基于Spring Boot和WTP的线程池管理系统 ## 项目简介 WTP(Web Thread Pool)是一个轻量级的线程池管理系统,旨在集中管理不同应用、不同集群的线程配置。通过WTP,用户可以动态修改线程池参数,并实时刷新配置,...
android线程池管理工具类,用来管理线程的一些操作,避免重复new线程造成的资源浪费
以上是对"ThreadPoolManager_线程池管理"的相关知识点的详细阐述,包括线程池的基本概念、ThreadPoolExecutor的使用、拒绝策略、生命周期以及线程池的最佳实践。在实际项目中,合理地使用线程池可以显著提高程序的...
本文将深入探讨一种基于配置中心的轻量级动态线程池,该线程池内置监控告警功能,且支持与多种常用中间件的线程池管理集成,允许通过SPI(Service Provider Interface)自定义扩展实现,以满足不同场景下的需求。...
ThreadPool 线程池管理单元 带调用例子
在这个"用C#开发的线程池管理器MyThreadPool"项目中,我们可以深入理解线程池的原理和如何自定义线程池来满足特定需求。 线程池是一种线程复用技术,它可以预先创建并维护一组线程,当需要执行任务时,不再每次都...
《EasyThread:安全轻巧的线程池管理器解析》 在Java开发中,线程池是一种高效且可控的多线程处理方式,它能够帮助我们更好地管理和调度系统资源,提高程序的执行效率。EasyThread是一款针对Java开发设计的安全、...
### Java线程池管理类:Executors_ #### 概述 `java.util.concurrent.Executors` 是Java并发编程中一个非常重要的工具类,主要用于创建不同类型的线程池对象。通过使用`Executors`类,开发者可以方便地管理和控制...
下面将详细阐述线程池的工作原理、优势以及如何在实际应用中创建和管理线程池。 1. **线程池工作原理** 线程池由一组可重用的线程组成,当有新的任务需要执行时,线程池会从已创建的线程中选择一个空闲线程来执行...
C#管理线程池的类 /* How to use Thread Classs * * ============== * public ELMService() { InitializeComponent(); etm.ClalThreadPool("EmailThreads", (uint)ApplicationInfo.EmailParsingThreads); ...