|
|
@@ -1,59 +1,59 @@
|
|
|
-# 基于 RT-Thread 的线程池实现
|
|
|
+# 鍩轰簬 RT-Thread 鐨勭嚎绋嬫睜瀹炵幇
|
|
|
|
|
|
---
|
|
|
|
|
|
-## 1、 基本介绍
|
|
|
+## 1銆� 鍩烘湰浠嬬粛
|
|
|
|
|
|
-### 1.1 线程池
|
|
|
+### 1.1 绾跨▼姹�
|
|
|
|
|
|
-线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务。
|
|
|
+绾跨▼姹犳槸涓€绉嶅�绾跨▼澶勭悊褰㈠紡锛屽�鐞嗚繃绋嬩腑灏嗕换鍔℃坊鍔犲埌闃熷垪锛岀劧鍚庡湪鍒涘缓绾跨▼鍚庤嚜鍔ㄥ惎鍔ㄨ繖浜涗换鍔°€�
|
|
|
|
|
|
-- 线程池管理器(ThreadPoolManager):用于创建并管理线程池;
|
|
|
-- 工作线程(WorkThread):线程池中的线程;
|
|
|
-- 任务接口(Task):每个任务必须实现的接口,以供工作线程调度任务的执行;
|
|
|
-- 任务队列(queue):用于存放没有处理的任务。提供一种缓冲机制。
|
|
|
+- 绾跨▼姹犵�鐞嗗櫒锛圱hreadPoolManager锛夛細鐢ㄤ簬鍒涘缓骞剁�鐞嗙嚎绋嬫睜锛�
|
|
|
+- 宸ヤ綔绾跨▼锛圵orkThread锛夛細绾跨▼姹犱腑鐨勭嚎绋嬶紱
|
|
|
+- 浠诲姟鎺ュ彛锛圱ask锛夛細姣忎釜浠诲姟蹇呴』瀹炵幇鐨勬帴鍙o紝浠ヤ緵宸ヤ綔绾跨▼璋冨害浠诲姟鐨勬墽琛岋紱
|
|
|
+- 浠诲姟闃熷垪锛坬ueue锛夛細鐢ㄤ簬瀛樻斁娌℃湁澶勭悊鐨勪换鍔°€傛彁渚涗竴绉嶇紦鍐叉満鍒躲€�
|
|
|
|
|
|
-### 1.2 线程池的由来
|
|
|
+### 1.2 绾跨▼姹犵殑鐢辨潵
|
|
|
|
|
|
-在面向对象编程中,创建和销毁对象是很费时间的,因为创建一个对象要获取内存资源或者其它更多资源。在Java中更是如此,虚拟机将试图跟踪每一个对象,以便能够在对象销毁后进行垃圾回收。所以提高服务程序效率的一个手段就是尽可能减少创建和销毁对象的次数,特别是一些很耗资源的对象创建和销毁。如何利用已有对象来服务就是一个需要解决的关键问题,其实这就是一些"池化资源"技术产生的原因。线程池也是由此而来。
|
|
|
+鍦ㄩ潰鍚戝�璞$紪绋嬩腑锛屽垱寤哄拰閿€姣佸�璞℃槸寰堣垂鏃堕棿鐨勶紝鍥犱负鍒涘缓涓€涓��璞¤�鑾峰彇鍐呭瓨璧勬簮鎴栬€呭叾瀹冩洿澶氳祫婧愩€傚湪Java涓�洿鏄��姝わ紝铏氭嫙鏈哄皢璇曞浘璺熻釜姣忎竴涓��璞★紝浠ヤ究鑳藉�鍦ㄥ�璞¢攢姣佸悗杩涜�鍨冨溇鍥炴敹銆傛墍浠ユ彁楂樻湇鍔$▼搴忔晥鐜囩殑涓€涓�墜娈靛氨鏄�敖鍙�兘鍑忓皯鍒涘缓鍜岄攢姣佸�璞$殑娆℃暟锛岀壒鍒�槸涓€浜涘緢鑰楄祫婧愮殑瀵硅薄鍒涘缓鍜岄攢姣併€傚�浣曞埄鐢ㄥ凡鏈夊�璞℃潵鏈嶅姟灏辨槸涓€涓�渶瑕佽В鍐崇殑鍏抽敭闂��锛屽叾瀹炶繖灏辨槸涓€浜�"姹犲寲璧勬簮"鎶€鏈�骇鐢熺殑鍘熷洜銆傜嚎绋嬫睜涔熸槸鐢辨�鑰屾潵銆�
|
|
|
|
|
|
-> 本线程池的实现来源于 <https://github.com/armink/EasyDataManager> 开源项目
|
|
|
+> 鏈�嚎绋嬫睜鐨勫疄鐜版潵婧愪簬 <https://github.com/armink/EasyDataManager> 寮€婧愰」鐩�
|
|
|
|
|
|
-## 2、 应用场景
|
|
|
+## 2銆� 搴旂敤鍦烘櫙
|
|
|
|
|
|
-使用线程池是为了减小线程本身的开销对应用性能所产生的影响,但是其前提是线程本身创建、销毁的开销和线程执行任务的开销相比是不可忽略的。如果线程本身创建、销毁的开销对应用程序的性能可以忽略不计,那么使用/不使用线程池对程序的性能并不会有太大的影响。
|
|
|
+浣跨敤绾跨▼姹犳槸涓轰簡鍑忓皬绾跨▼鏈�韩鐨勫紑閿€瀵瑰簲鐢ㄦ€ц兘鎵€浜х敓鐨勫奖鍝嶏紝浣嗘槸鍏跺墠鎻愭槸绾跨▼鏈�韩鍒涘缓銆侀攢姣佺殑寮€閿€鍜岀嚎绋嬫墽琛屼换鍔$殑寮€閿€鐩告瘮鏄�笉鍙�拷鐣ョ殑銆傚�鏋滅嚎绋嬫湰韬�垱寤恒€侀攢姣佺殑寮€閿€瀵瑰簲鐢ㄧ▼搴忕殑鎬ц兘鍙�互蹇界暐涓嶈�锛岄偅涔堜娇鐢�/涓嶄娇鐢ㄧ嚎绋嬫睜瀵圭▼搴忕殑鎬ц兘骞朵笉浼氭湁澶�ぇ鐨勫奖鍝嶃€�
|
|
|
|
|
|
-- 单位时间内处理的任务频繁,且任务时间较短;
|
|
|
-- 对实时性要求较高。如果接收到任务之后再创建线程,可能无法满足实时性的要求,此时必须使用线程池;
|
|
|
-- 必须经常面对高突发性事件。比如 Web 服务器。如果有足球转播,则服务器将产生巨大冲击,此时使用传统方法,则必须不停的大量创建、销毁线程。此时采用动态线程池可以避免这种情况的发生。
|
|
|
+- 鍗曚綅鏃堕棿鍐呭�鐞嗙殑浠诲姟棰戠箒锛屼笖浠诲姟鏃堕棿杈冪煭锛�
|
|
|
+- 瀵瑰疄鏃舵€ц�姹傝緝楂樸€傚�鏋滄帴鏀跺埌浠诲姟涔嬪悗鍐嶅垱寤虹嚎绋嬶紝鍙�兘鏃犳硶婊¤冻瀹炴椂鎬х殑瑕佹眰锛屾�鏃跺繀椤讳娇鐢ㄧ嚎绋嬫睜锛�
|
|
|
+- 蹇呴』缁忓父闈㈠�楂樼獊鍙戞€т簨浠躲€傛瘮濡� Web 鏈嶅姟鍣ㄣ€傚�鏋滄湁瓒崇悆杞�挱锛屽垯鏈嶅姟鍣ㄥ皢浜х敓宸ㄥぇ鍐插嚮锛屾�鏃朵娇鐢ㄤ紶缁熸柟娉曪紝鍒欏繀椤讳笉鍋滅殑澶ч噺鍒涘缓銆侀攢姣佺嚎绋嬨€傛�鏃堕噰鐢ㄥ姩鎬佺嚎绋嬫睜鍙�互閬垮厤杩欑�鎯呭喌鐨勫彂鐢熴€�
|
|
|
|
|
|
-## 3、用法
|
|
|
+## 3銆佺敤娉�
|
|
|
|
|
|
-主要通过以下六点介绍如何使用线程池:
|
|
|
+涓昏�閫氳繃浠ヤ笅鍏�偣浠嬬粛濡備綍浣跨敤绾跨▼姹狅細
|
|
|
|
|
|
-- 定义线程池
|
|
|
-- 初始化线程池
|
|
|
-- 添加任务到线程池
|
|
|
-- 销毁线程池
|
|
|
-- 同步锁
|
|
|
-- 释放同步锁
|
|
|
+- 瀹氫箟绾跨▼姹�
|
|
|
+- 鍒濆�鍖栫嚎绋嬫睜
|
|
|
+- 娣诲姞浠诲姟鍒扮嚎绋嬫睜
|
|
|
+- 閿€姣佺嚎绋嬫睜
|
|
|
+- 鍚屾�閿�
|
|
|
+- 閲婃斁鍚屾�閿�
|
|
|
|
|
|
-### 3.1 定义线程池
|
|
|
+### 3.1 瀹氫箟绾跨▼姹�
|
|
|
|
|
|
-通过 **thread_pool** 或 **thread_pool_t** 定义线程池
|
|
|
+閫氳繃 **thread_pool** 鎴� **thread_pool_t** 瀹氫箟绾跨▼姹�
|
|
|
|
|
|
```c
|
|
|
-//方式一 结构体类型
|
|
|
+//鏂瑰紡涓€ 缁撴瀯浣撶被鍨�
|
|
|
thread_pool pool;
|
|
|
|
|
|
-//方式二 结构体指针类型
|
|
|
+//鏂瑰紡浜� 缁撴瀯浣撴寚閽堢被鍨�
|
|
|
thread_pool_t pool;
|
|
|
```
|
|
|
-*注:本文采用**方式一**定义线程池*
|
|
|
+*娉�細鏈�枃閲囩敤**鏂瑰紡涓€**瀹氫箟绾跨▼姹�*
|
|
|
|
|
|
-### 3.2 初始化线程池
|
|
|
+### 3.2 鍒濆�鍖栫嚎绋嬫睜
|
|
|
|
|
|
-- 原型
|
|
|
+- 鍘熷瀷
|
|
|
|
|
|
```c
|
|
|
init_thread_pool(thread_pool_t const pool,
|
|
|
@@ -63,17 +63,17 @@ init_thread_pool(thread_pool_t const pool,
|
|
|
|
|
|
- API
|
|
|
|
|
|
-|参数|名称|类型|描述|
|
|
|
+|鍙傛暟|鍚嶇О|绫诲瀷|鎻忚堪|
|
|
|
|:---|:---|:---|:---|
|
|
|
-|入参|pool|thread_pool_t|对象|
|
|
|
-|入参|max_thread_num|uint8_t|线程数量|
|
|
|
-|入参|thread_stack|uint32_t|堆栈大小|
|
|
|
-|返回值|error_code|thread_pool_err|返回状态|
|
|
|
+|鍏ュ弬|pool|thread_pool_t|瀵硅薄|
|
|
|
+|鍏ュ弬|max_thread_num|uint8_t|绾跨▼鏁伴噺|
|
|
|
+|鍏ュ弬|thread_stack|uint32_t|鍫嗘爤澶у皬|
|
|
|
+|杩斿洖鍊紎error_code|thread_pool_err|杩斿洖鐘舵€亅
|
|
|
|
|
|
|
|
|
- Demo
|
|
|
|
|
|
-创建一个线程数量为5,堆栈大小为1024 Byte的线程池
|
|
|
+鍒涘缓涓€涓�嚎绋嬫暟閲忎负5锛屽爢鏍堝ぇ灏忎负1024 Byte鐨勭嚎绋嬫睜
|
|
|
|
|
|
```c
|
|
|
thread_pool pool;
|
|
|
@@ -81,9 +81,9 @@ thread_pool pool;
|
|
|
init_thread_pool(pool, "A", 5, 1024);
|
|
|
```
|
|
|
|
|
|
-### 3.3 添加任务
|
|
|
+### 3.3 娣诲姞浠诲姟
|
|
|
|
|
|
-- 原型
|
|
|
+- 鍘熷瀷
|
|
|
|
|
|
```c
|
|
|
add_task(thread_pool_t const pool,
|
|
|
@@ -92,33 +92,33 @@ add_task(thread_pool_t const pool,
|
|
|
```
|
|
|
- API
|
|
|
|
|
|
-|参数|名称|类型|描述|
|
|
|
+|鍙傛暟|鍚嶇О|绫诲瀷|鎻忚堪|
|
|
|
|:---|:---|:---|:---|
|
|
|
-|入参|pool|thread_pool_t|对象|
|
|
|
-|入参|process(void *arg)|void|任务处理函数|
|
|
|
-|入参|arg|void *|任务处理函数入参|
|
|
|
-|返回值|error_code|thread_pool_err|返回状态|
|
|
|
+|鍏ュ弬|pool|thread_pool_t|瀵硅薄|
|
|
|
+|鍏ュ弬|process(void *arg)|void|浠诲姟澶勭悊鍑芥暟|
|
|
|
+|鍏ュ弬|arg|void *|浠诲姟澶勭悊鍑芥暟鍏ュ弬|
|
|
|
+|杩斿洖鍊紎error_code|thread_pool_err|杩斿洖鐘舵€亅
|
|
|
|
|
|
|
|
|
- Demo
|
|
|
|
|
|
-线程池中添加任务 task1,启动时够通过日志看到 task1 在线程池A中的运行效果。
|
|
|
+绾跨▼姹犱腑娣诲姞浠诲姟 task1锛屽惎鍔ㄦ椂澶熼€氳繃鏃ュ織鐪嬪埌 task1 鍦ㄧ嚎绋嬫睜A涓�殑杩愯�鏁堟灉銆�
|
|
|
|
|
|
```c
|
|
|
char str_a[]="A";
|
|
|
-//任务处理函数
|
|
|
+//浠诲姟澶勭悊鍑芥暟
|
|
|
static void *task1(void *arg) {
|
|
|
LOG_D("This is %s test ",(char*)arg);
|
|
|
return NULL;
|
|
|
}
|
|
|
-//添加任务
|
|
|
+//娣诲姞浠诲姟
|
|
|
pool.addTask(&pool, task1, str_a);
|
|
|
|
|
|
```
|
|
|
|
|
|
-### 3.4 销毁线程池
|
|
|
+### 3.4 閿€姣佺嚎绋嬫睜
|
|
|
|
|
|
-- 原型
|
|
|
+- 鍘熷瀷
|
|
|
|
|
|
```c
|
|
|
destroy(thread_pool_t pool);
|
|
|
@@ -126,31 +126,31 @@ destroy(thread_pool_t pool);
|
|
|
|
|
|
- API
|
|
|
|
|
|
-|参数|名称|类型|描述|
|
|
|
+|鍙傛暟|鍚嶇О|绫诲瀷|鎻忚堪|
|
|
|
|:---|:---|:---|:---|
|
|
|
-|入参|pool|thread_pool_t|对象|
|
|
|
-|返回值|error_code|thread_pool_err|返回状态|
|
|
|
+|鍏ュ弬|pool|thread_pool_t|瀵硅薄|
|
|
|
+|杩斿洖鍊紎error_code|thread_pool_err|杩斿洖鐘舵€亅
|
|
|
|
|
|
|
|
|
- Demo
|
|
|
|
|
|
-销毁线程池
|
|
|
+閿€姣佺嚎绋嬫睜
|
|
|
|
|
|
```c
|
|
|
pool.destroy(&pool);
|
|
|
```
|
|
|
-### 3.5 同步锁
|
|
|
+### 3.5 鍚屾�閿�
|
|
|
|
|
|
-- 原型
|
|
|
+- 鍘熷瀷
|
|
|
```c
|
|
|
-sync_lock(thread_pool_t pool);
|
|
|
+sync_lock(thread_pool_t pool)锛�
|
|
|
```
|
|
|
- API
|
|
|
|
|
|
-|入参|名称|类型|描述|
|
|
|
+|鍏ュ弬|鍚嶇О|绫诲瀷|鎻忚堪|
|
|
|
|:---|:---|:---|:---|
|
|
|
-|入参|pool|thread_pool_t|对象|
|
|
|
-|返回值|NULL|void*|返回状态|
|
|
|
+|鍏ュ弬|pool|thread_pool_t|瀵硅薄|
|
|
|
+|杩斿洖鍊紎NULL|void*|杩斿洖鐘舵€亅
|
|
|
|
|
|
|
|
|
- Demo
|
|
|
@@ -159,20 +159,20 @@ sync_lock(thread_pool_t pool)
|
|
|
pool.lock(&pool);
|
|
|
```
|
|
|
|
|
|
-### 3.6 释放同步锁
|
|
|
+### 3.6 閲婃斁鍚屾�閿�
|
|
|
|
|
|
-- 原型
|
|
|
+- 鍘熷瀷
|
|
|
|
|
|
```c
|
|
|
-sync_unlock(thread_pool_t pool);
|
|
|
+sync_unlock(thread_pool_t pool)锛�
|
|
|
```
|
|
|
|
|
|
- API
|
|
|
|
|
|
-|入参|名称|类型|描述|
|
|
|
+|鍏ュ弬|鍚嶇О|绫诲瀷|鎻忚堪|
|
|
|
|:---|:---|:---|:---|
|
|
|
-|入参|pool|thread_pool_t|对象|
|
|
|
-|返回值|NULL|void*|返回状态|
|
|
|
+|鍏ュ弬|pool|thread_pool_t|瀵硅薄|
|
|
|
+|杩斿洖鍊紎NULL|void*|杩斿洖鐘舵€亅
|
|
|
|
|
|
|
|
|
- Demo
|
|
|
@@ -181,9 +181,9 @@ sync_unlock(thread_pool_t pool)
|
|
|
pool.unlock(&pool);
|
|
|
```
|
|
|
|
|
|
-## 4、示例
|
|
|
+## 4銆佺ず渚�
|
|
|
|
|
|
-代码位于 thread_pool_sample.c ,源码大致如下:
|
|
|
+浠g爜浣嶄簬 thread_pool_sample.c 锛屾簮鐮佸ぇ鑷村�涓嬶細
|
|
|
|
|
|
```c
|
|
|
#include <finsh.h>
|
|
|
@@ -215,17 +215,17 @@ static void thread_pool_sample(uint8_t argc, char **argv) {
|
|
|
MSH_CMD_EXPORT(thread_pool_sample, Run thread pool sample);
|
|
|
```
|
|
|
|
|
|
-功能流程大致如下:
|
|
|
+鍔熻兘娴佺▼澶ц嚧濡備笅锛�
|
|
|
|
|
|
-- thread_pool_sample 中会初始化一个包含有 3 个线程的线程池
|
|
|
-- 向线程池中一次性添加 5 个任务
|
|
|
-- 每个任务执行时会延时 5S 的随机值
|
|
|
-- 等待 10 S 删除线程中剩余的全部任务
|
|
|
-- 销毁线程池
|
|
|
+- thread_pool_sample 涓�細鍒濆�鍖栦竴涓�寘鍚�湁 3 涓�嚎绋嬬殑绾跨▼姹�
|
|
|
+- 鍚戠嚎绋嬫睜涓�竴娆℃€ф坊鍔� 5 涓�换鍔�
|
|
|
+- 姣忎釜浠诲姟鎵ц�鏃朵細寤舵椂 5S 鐨勯殢鏈哄€�
|
|
|
+- 绛夊緟 10 S 鍒犻櫎绾跨▼涓�墿浣欑殑鍏ㄩ儴浠诲姟
|
|
|
+- 閿€姣佺嚎绋嬫睜
|
|
|
|
|
|
-使用前需在 menuconfig 中开启 `THREAD_POOL_USING_SAMPLES` 选项。
|
|
|
+浣跨敤鍓嶉渶鍦� menuconfig 涓�紑鍚� `THREAD_POOL_USING_SAMPLES` 閫夐」銆�
|
|
|
|
|
|
-开启后,在 Finsh/MSH 中执行 `thread_pool_sample` 命令,即可看到示例运行效果,大致如下:
|
|
|
+寮€鍚�悗锛屽湪 Finsh/MSH 涓�墽琛� `thread_pool_sample` 鍛戒护锛屽嵆鍙�湅鍒扮ず渚嬭繍琛屾晥鏋滐紝澶ц嚧濡備笅锛�
|
|
|
|
|
|
```shell
|
|
|
msh />thread_pool_sample
|
|
|
@@ -252,7 +252,7 @@ msh />thread_pool_sample
|
|
|
[D/thread_pool] Thread pool destroy success
|
|
|
```
|
|
|
|
|
|
-## 5、联系方式
|
|
|
+## 5銆佽仈绯绘柟寮�
|
|
|
|
|
|
-* 维护:[armink](https://github.com/armink)
|
|
|
-* 主页:https://github.com/armink-rtt-pkgs/thread_pool
|
|
|
+* 缁存姢锛歔armink](https://github.com/armink)
|
|
|
+* 涓婚〉锛歨ttps://github.com/armink-rtt-pkgs/thread_pool
|