通常我们使用多线程的方式是,需要时创建一个新的线程,在这个新的线程里执行特定的任务,然后在任务完成后退出。这在一般的应用里已经能够满足我们应用的需要,毕竟我们并不是什么时候都需要创建大量的线程,并在它们执行一个简单的任务后销毁。 但是在一些web、email、database等应用里,比如彩铃,我们的应用在任何时候都要准备应对数目巨大的连接请求,同时,这些请求所要完成的任务却又可能非常的简单,即只占用很少的处理时间。这时,我们的应用有可能处于不停的创建线程并销毁线程的状态。虽说比起进程的创建,线程的创建时间已经大大缩短,但是如果需要频繁的创建线程,并且每个线程所占用的处理时间又非常简短,则线程创建和销毁带给处理器的额外负担也是很可观的。 线程池的作用正是在这种情况下有效的降低频繁创建销毁线程所带来的额外开销。一般来说,线程池都是采用预创建的技术,在应用启动之初便预先创建一定数目的线程。应用在运行的过程中,需要时可以从这些线程所组成的线程池里申请分配一个空闲的线程,来执行一定的任务,任务完成后,并不是将线程销毁,而是将它返还给线程池,由线程池自行管理。如果线程池中预先分配的线程已经全部分配完毕,但此时又有新的任务请求,则线程池会动态的创建新的线程去适应这个请求。当然,有可能,某些时段应用并不需要执行很多的任务,导致了线程池中的线程大多处于空闲的状态,为了节省系统资源,线程池就需要动态的销毁其中的一部分空闲线程。因此,线程池都需要一个管理者,按照一定的要求去动态的维护其中线程的数目。 基于上面的技术,线程池将频繁创建和销毁线程所带来的开销分摊到了每个具体执行的任务上,执行的次数越多,则分摊到每个任务上的开销就越小。 当然,如果线程创建销毁所带来的开销与线程执行任务的开销相比微不足道,可以忽略不计,则线程池并没有使用的必要。比如,FTP、Telnet等应用时。 现在已经可以从网上找到一些线程池的实例,但它们一般都是使用C++、Java等语言实现的,如果我们使用C实现我们的应用的话,使用起来就会遇到麻烦。基于此,利用上面的框架,我使用C实现了一个简单的线程池库,代码可以从 https://sourceforge.net/projects/libthreadpool 下载。 为了使这个线程池库使用起来更加方便,我在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接口销毁它。
分享到:
相关推荐
### Linux线程池C源码解析 #### 一、概览 本文将深入解析一个Linux下的线程池实现,该实现使用C语言编写,并遵循GNU通用公共许可证版本2(或之后版本)。线程池是一种软件设计模式,它可以提高程序执行效率,通过...
本项目涉及的核心知识点是“Linux下的socket线程池实现”,这涉及到多个技术层面,包括socket编程、多线程技术和线程池的管理。 首先,让我们了解什么是Socket。Socket是网络通信的基本接口,它允许应用程序通过...
通过Source Insight这样的源代码分析工具,我们可以更方便地查看和理解代码结构,定位函数调用,追踪变量变化,这对于理解和优化线程池的实现非常有帮助。 在实际应用中,线程池广泛应用于服务器端编程、多任务处理...
总结起来,Linux C系统编程中使用线程池实现类似`cp`命令的功能,是一个涉及多线程编程、任务调度和同步控制的综合实践。通过这样的实现,我们可以提高文件复制操作的并发性和效率,同时降低系统资源的消耗。在深入...
### Linux线程池实现 #### 一、线程池概念及意义 线程池是一种用于管理线程资源的机制,在Linux环境下尤为重要。通过线程池,可以预先创建一定数量的线程并将其放入一个池中等待任务分配。这种方式能够有效地减少...
本文将深入探讨Linux线程池的实现原理,并提供实例分析。 ### 1. 线程池的基本概念 线程池由一组工作线程、一个任务队列和一组控制机制组成。工作线程负责从任务队列中取出任务并执行,任务队列用于存储待处理的...
在"Linux线程池代码.zip"这个压缩包中,我们可以期待找到一个用C语言编写的线程池实现。线程池的核心概念包括以下几个部分: 1. **线程池初始化**:程序启动时,首先会创建一个线程池,这个过程需要指定线程池的...
本文将深入探讨“Linux线程池”这一主题,以及如何在C++中实现东方国信计费线程池。 线程池的概念源于操作系统理论,它是指预先创建一组线程,这些线程共享一个任务队列。当有新任务到来时,线程池中的空闲线程会被...
总的来说,C++封装的Linux线程池是利用C++的多线程特性和系统级接口(如POSIX线程库)实现的并发处理工具,它能有效地提升系统性能,同时降低资源消耗。通过阅读和分析"ThreadPool.cpp"和"ThreadPool.h",开发者可以...
在这个简单的线程池实现中,我们可以通过`pthread_pool.cpp`、`MainFunctionForTest.cpp`、`twork_work.cpp`、`pthread_pool.h`和`twork_work.h`这五个文件来理解其基本架构和工作原理。 首先,`pthread_pool.h`...
### Linux线程池知识点解析 #### 一、线程池概念 线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务。线程池的主要目的是提高响应速度并减少资源消耗。 #### 二、线程池...
Java中,`java.util.concurrent.ThreadPoolExecutor`提供了内置的线程池实现。 6. **线程池参数**:线程池的性能很大程度上取决于参数设置,包括核心线程数、最大线程数、线程存活时间、任务队列容量等。这些参数...
《基于Linux多线程管理的分析与实现》这篇文章主要探讨了如何在Linux环境下有效地管理和实现多线程,以防止线程并发混乱和进程异常结束,从而提高程序的稳定性和效率。文章结合POSIX Threads库的功能,提出了线程...
本篇文章将深入探讨Linux线程池的原理、实现方式以及它在实际应用中的优势。 线程池的基本结构通常包括以下几个部分: 1. **线程池管理器**:负责创建、管理和调度线程池中的工作线程。当有新的任务到来时,管理器...
通过对压缩包内的Linux源码进行分析,我们可以学习如何在C语言环境中设计和实现线程池,以及如何将线程池应用到客户端和服务端的网络通信中,这将有助于深化对多线程编程和系统级编程的理解。 总的来说,这个...
本资源提供的线程池实现是一个简单而实用的例子,特别适合对C++多线程编程感兴趣或需要在Linux环境中应用线程池技术的开发者。 首先,C++11标准引入了线程库 `<thread>`,使得在C++中进行多线程编程变得更为便捷。...
### Linux环境下通用线程池设计的关键知识点 #### 一、设计背景与意义 在Linux环境中,服务器往往需要处理大量的并发请求,并确保应用的稳定性和高效性。为了满足这些需求,通常采用多进程或多线程的技术来提升...
本实例提供了一个简单的Linux C线程池实现,可用于学习和实验。通过对线程池基本概念的理解,我们可以更高效地管理多线程程序中的线程生命周期,从而提高程序的整体性能。此外,通过深入分析源代码,还可以进一步...
本教程将深入探讨如何在Linux环境下,使用C++实现一个简单的线程池。 首先,线程池的基本结构通常包括以下几个部分: 1. **线程池容器**:用于存储工作线程的集合,通常使用STL中的`std::vector`来实现。这个容器...