網(wǎng)站首頁 編程語言 正文
什么是線程
線程是進(jìn)程中的?個執(zhí)?單元,負(fù)責(zé)當(dāng)前進(jìn)程中程序的執(zhí)?,?個進(jìn)程中?少有?個線程。?個進(jìn)程中是可以有多個線程的,這個應(yīng)?程序也可以稱之為多線程程序。多線程程序作為一種多任務(wù)、并發(fā)的工作方式
并發(fā)與并?
早期計(jì)算機(jī)的 CPU 都是單核的,一個 CPU 在同一時間只能執(zhí)行一個進(jìn)程/線程,當(dāng)系統(tǒng)中有多個進(jìn)程/線程等待執(zhí)行時,CPU 只能執(zhí)行完一個再執(zhí)行下一個。為了提高 CPU 利用率,減少等待時間,人們提出了一種 CPU 并發(fā)工作的理論.
并發(fā):指兩個或多個事件在同?個時間段內(nèi)發(fā)?,當(dāng)系統(tǒng)中有多個進(jìn)程/線程等待執(zhí)行時,CPU只能執(zhí)行完一個再執(zhí)行下一個。
并?:指兩個或多個事件在同?時刻發(fā)?(同時發(fā)?),多核 CPU 的每個核心都可以獨(dú)立地執(zhí)行一個任務(wù),而且多個核心之間不會相互干擾。在不同核心上執(zhí)行的多個任務(wù),是真正地同時運(yùn)行,這種狀態(tài)就叫做并行。。
什么是線程池
顧名思義:線程池就是線程的池子,有很多線程,但是數(shù)量不會超過池子的限制。需要用到多執(zhí)行流進(jìn)行任務(wù)出路的時候,就從池子中取出一個線程去處理,線程池就類似于一個實(shí)現(xiàn)了消費(fèi)者業(yè)務(wù)的生產(chǎn)者與消費(fèi)者模型。
本質(zhì)上:這就是一個基于生產(chǎn)者消費(fèi)者模型來實(shí)現(xiàn)的線程池,那么同樣遵守三種規(guī)則,生產(chǎn)者和生產(chǎn)者之間存在互斥,處理任務(wù)的線程之間存在互斥關(guān)系,生產(chǎn)者和消費(fèi)者之間存在同步和互斥關(guān)系
線程池解決什么問題
線程池維護(hù)者多個線程,等待著分配可并發(fā)執(zhí)行的任務(wù),可以避免在短時間創(chuàng)建和銷毀大量線程帶來時間成本。
總結(jié)為三點(diǎn):
1.避免線程因?yàn)椴幌拗苿?chuàng)建數(shù)量導(dǎo)致的資源耗盡風(fēng)險
2.任務(wù)隊(duì)列緩沖任務(wù),支持忙線不均的作用
3.節(jié)省了大量頻繁創(chuàng)建/銷毀線程的時間成本
怎么用線程池
下面展示一些 threadpool
實(shí)現(xiàn),源碼來自openharmony。
/* * Copyright (c) 2022 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef NETSTACK_THREAD_POOL #define NETSTACK_THREAD_POOL #include <atomic> #include <condition_variable> #include <queue> #include <thread> #include <vector> namespace OHOS::NetStack { template <typename Task, const size_t DEFAULT_THREAD_NUM, const size_t MAX_THREAD_NUM> class ThreadPool { public: /** * disallow default constructor */ ThreadPool() = delete; /** * disallow copy and move */ ThreadPool(const ThreadPool &) = delete; /** * disallow copy and move */ ThreadPool &operator=(const ThreadPool &) = delete; /** * disallow copy and move */ ThreadPool(ThreadPool &&) = delete; /** * disallow copy and move */ ThreadPool &operator=(ThreadPool &&) = delete; /** * make DEFAULT_THREAD_NUM threads * @param timeout if timeout and runningThreadNum_ < DEFAULT_THREAD_NUM, the running thread should be terminated */ explicit ThreadPool(uint32_t timeout) : timeout_(timeout), idleThreadNum_(0), needRun_(true) { for (int i = 0; i < DEFAULT_THREAD_NUM; ++i) { std::thread([this] { RunTask(); }).detach(); } } /** * if ~ThreadPool, terminate all thread */ ~ThreadPool() { // set needRun_ = false, and notify all the thread to wake and terminate needRun_ = false; while (runningNum_ > 0) { needRunCondition_.notify_all(); } } /** * push it to taskQueue_ and notify a thread to run it * @param task new task to Execute */ void Push(const Task &task) { PushTask(task); if (runningNum_ < MAX_THREAD_NUM && idleThreadNum_ == 0) { std::thread([this] { RunTask(); }).detach(); } needRunCondition_.notify_all(); } private: bool IsQueueEmpty() { std::lock_guard<std::mutex> guard(mutex_); return taskQueue_.empty(); } bool GetTask(Task &task) { std::lock_guard<std::mutex> guard(mutex_); // if taskQueue_ is empty, means timeout if (taskQueue_.empty()) { return false; } // if run to this line, means that taskQueue_ is not empty task = taskQueue_.top(); taskQueue_.pop(); return true; } void PushTask(const Task &task) { std::lock_guard<std::mutex> guard(mutex_); taskQueue_.push(task); } class NumWrapper { public: NumWrapper() = delete; explicit NumWrapper(std::atomic<uint32_t> &num) : num_(num) { ++num_; } ~NumWrapper() { --num_; } private: std::atomic<uint32_t> &num_; }; void Sleep() { std::mutex needRunMutex; std::unique_lock<std::mutex> lock(needRunMutex); /** * if the thread is waiting, it is idle * if wake up, this thread is not idle: * 1 this thread should return * 2 this thread should run task * 3 this thread should go to next loop */ NumWrapper idleWrapper(idleThreadNum_); (void)idleWrapper; needRunCondition_.wait_for(lock, std::chrono::seconds(timeout_), [this] { return !needRun_ || !IsQueueEmpty(); }); } void RunTask() { NumWrapper runningWrapper(runningNum_); (void)runningWrapper; while (needRun_) { Task task; if (GetTask(task)) { task.Execute(); continue; } Sleep(); if (!needRun_) { return; } if (GetTask(task)) { task.Execute(); continue; } if (runningNum_ > DEFAULT_THREAD_NUM) { return; } } } private: /** * other thread put a task to the taskQueue_ */ std::mutex mutex_; std::priority_queue<Task> taskQueue_; /** * 1 terminate the thread if it is idle for timeout_ seconds * 2 wait for the thread started util timeout_ * 3 wait for the thread notified util timeout_ * 4 wait for the thread terminated util timeout_ */ uint32_t timeout_; /** * if idleThreadNum_ is zero, make a new thread */ std::atomic<uint32_t> idleThreadNum_; /** * when ThreadPool object is deleted, wait until runningNum_ is zero. */ std::atomic<uint32_t> runningNum_; /** * when ThreadPool object is deleted, set needRun_ to false, mean that all thread should be terminated */ std::atomic_bool needRun_; std::condition_variable needRunCondition_; }; } // namespace OHOS::NetStack #endif /* NETSTACK_THREAD_POOL */
這份源碼的實(shí)現(xiàn),沒有使用一些較難理解的語法,基本上就是使用線程+優(yōu)先級隊(duì)列實(shí)現(xiàn)的。提前創(chuàng)建指定數(shù)目的線程,每次取一個任務(wù)并執(zhí)行。任務(wù)隊(duì)列負(fù)責(zé)存放線程需要處理的任務(wù),工作線程負(fù)責(zé)從任務(wù)隊(duì)列中取出和運(yùn)行任務(wù),可以看成是一個生產(chǎn)者和多個消費(fèi)者的模型。
#include "doctest.h" DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN #include <stdexcept> DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END //#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN //#define DOCTEST_CONFIG_DISABLE #include <string> #include <iostream> #include "thread_pool.h" // // Created by Administrator on 2022/8/10. // class Task { public: Task() = default; explicit Task(std::string context){ mContext = context; } bool operator<(const Task &e) const{ return priority_ < e.priority_; } void Execute(){ std::lock_guard<std::mutex> guard(mutex_); std::cout << "task is execute,name is:"<<mContext<<std::endl; } public: uint32_t priority_; private: std::string mContext; static std::mutex mutex_; }; #define DEFAULT_THREAD_NUM 3 #define MAX_THREAD_NUM 6 #define TIME_OUT 500 std::mutex Task::mutex_; static int threadpoolTest(){ static OHOS_NetStack::ThreadPool<Task, DEFAULT_THREAD_NUM, MAX_THREAD_NUM> threadPool_(TIME_OUT); Task task1("name_1"); Task task2("name_2"); Task task3("name_3"); Task task4("name_4"); threadPool_.Push(task1); threadPool_.Push(task2); threadPool_.Push(task3); threadPool_.Push(task4); return 0; } TEST_CASE("threadPool simple use example, test by doctest unit tool") { threadpoolTest(); }
以上該版本thread_pool的簡單使用示例,可以看到使用稍微麻煩了些。必須定義格式如下的task類,必須實(shí)現(xiàn)operator<和Execute()方法,不過整體實(shí)現(xiàn)還是很不錯的,通俗易懂!
總結(jié)
線程池的應(yīng)用場景:當(dāng)有大量的數(shù)據(jù)請求,需要多執(zhí)行流并發(fā)/并行處理時,可以采用線程池來處理任務(wù),可避免大量線程頻繁創(chuàng)建或銷毀所帶來的時間成本,也可避免在峰值壓力下,系統(tǒng)資源耗盡的風(fēng)險。
原文鏈接:https://blog.csdn.net/weixin_44834554/article/details/126668425
相關(guān)推薦
- 2022-10-31 Python入門之字典的使用教程_python
- 2022-04-28 Python的命令行參數(shù)實(shí)例詳解_python
- 2022-09-22 k8s 配置存儲之 Configmap & secret
- 2022-11-28 Flutter?Widgets之標(biāo)簽類控件Chip詳解_IOS
- 2022-07-19 macOS Docker 內(nèi)存 CPU 占用過高,監(jiān)控到 com.Docker.hyperkit 進(jìn)
- 2022-10-14 cannot find symbol[ERROR] package sun.misc
- 2022-06-02 slf4j Logger使用{}占位符輸出日志
- 2022-04-20 Selenium?三種等待方式(強(qiáng)制等待、隱式等待、顯示等待)_python
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支