[C++][執行緒池][完整實現] 轉:執行緒池原理及建立(C++實現)
文章的主要框架是參考這篇文件的,http://jacky-dai.iteye.com/blog/1090285,
關於作者
張中慶,西安交通大學軟體所,在讀碩士,目前研究方向為分散式網路與移動中介軟體,對Linux極其愛好,可以通過[email protected]與我聯絡
其實看了好多類似的,都是沒有完整的實現,自己花了點時間把這個程式梳理了一下,寫了個測試程式,目前可以跑通。
#include <stdio.h> #include <stdlib.h> #include <vector> #include <algorithm> #include <assert.h> #include <Windows.h> #include <functional> #include <process.h> using namespace std; class CThread; //鎖的基類 class CLockObject { public: virtual BOOL Lock() = 0; virtual BOOL UnLock() = 0; }; //任務基類,所有要執行的任務都繼承這個類 class CJob { private: int m_JobNo;//任務ID 用來除錯是否繫結特定執行緒 char* m_JobName; //任務名字,用來除錯是否繫結特定執行緒 CThread* m_pWorkThread; //The thread associated with the job public: CJob(); virtual ~CJob(); CThread *GetWorkThread(void); //獲取工作執行緒 void SetWorkThread(CThread* pWorkThread);//設定工作執行緒 virtual void Execute(void* ptr) = 0; //執行函式 int GetJobNo(void) const { return m_JobNo; } void SetJobNo(int jobno){ m_JobNo = jobno;} char* GetJobName(void) const { return m_JobName; } void SetJobName(char* jobname); }; void CJob::SetJobName(char* jobname) { if(NULL !=m_JobName) { free(m_JobName); m_JobName = NULL; } if(NULL !=jobname) { m_JobName = (char*)malloc(strlen(jobname)+1); strcpy(m_JobName,jobname); } } CThread* CJob::GetWorkThread(void) { return m_pWorkThread; } void CJob::SetWorkThread(CThread *pWorkThread) { m_pWorkThread = pWorkThread; } CJob::CJob(void) :m_pWorkThread(NULL),m_JobName(NULL), m_JobNo(0) { } CJob::~CJob() { if (NULL != m_JobName) { free(m_JobName); m_JobName = NULL; } } //執行緒狀態 typedef enum _ThreadState { THREAD_RUNNING = 0x0, //執行 THREAD_IDLE = 0x1,//空閒 THREAD_EXIT = 0X2,//退出 }ThreadState; //執行緒基類 class CThread { private: int m_ErrorCode; //錯誤碼 unsigned long m_ThreadID; //執行緒ID char* m_ThreadName; //執行緒名字 ThreadState m_ThreadState; //執行緒狀態 HANDLE m_hthreadHandle; //執行緒控制代碼 bool m_IsExit;//是否退出 protected: static unsigned __stdcall ThreadFunction(void*); //start呼叫此函式,此函式再呼叫run函式,執行實際的任務 public: CThread(); virtual ~CThread(); virtual void Run() = 0; //設定執行緒狀態 void SetThreadState(ThreadState state); //獲取執行緒狀態 ThreadState GetThreadState(); //Start to execute the thread bool Start(); //獲取執行緒ID int GetThreadID(void); //設定錯誤碼 void SetErrorCode(int errorCode); //獲取錯誤碼 int GetLastError(void); //設定執行緒名字 void SetThreadName(char* threadName); //獲取執行緒名字 char* GetThreadName(); //設定執行緒優先順序 bool SetPriority(int priority); //獲取執行緒優先順序 int GetPriority(void); bool Terminate(void); HANDLE GetThreadHandle(); void SetThreadHandle(HANDLE hdl); void SetExitFlag(bool bExit); bool GetExitFlag(); bool NeedExit(); }; bool CThread::NeedExit() { return m_IsExit; } void CThread::SetExitFlag(bool bExit) { m_IsExit = bExit; } bool CThread::GetExitFlag() { return m_IsExit; } bool CThread::Terminate(void) { _endthreadex(0); return TRUE; } HANDLE CThread::GetThreadHandle() { return m_hthreadHandle; } void CThread::SetThreadHandle(HANDLE hdl) { m_hthreadHandle = hdl; } void CThread::SetErrorCode(int errorCode) { m_ErrorCode = errorCode; } int CThread::GetLastError(void) { return m_ErrorCode; } CThread::CThread() { m_IsExit = FALSE; } CThread::~CThread() { } void CThread::SetThreadState(ThreadState state) { m_ThreadState = state; } ThreadState CThread::GetThreadState() { return m_ThreadState; } //Start to execute the thread bool CThread::Start() { unsigned threadID; HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, ThreadFunction, this, 0, &threadID); this->m_ThreadID = threadID; this->SetThreadHandle(hThread); return true; } unsigned __stdcall CThread::ThreadFunction(void* pArg) { CThread* pThread = (CThread*)pArg; pThread->Run(); return TRUE; } int CThread::GetThreadID(void) { return m_ThreadID; } void CThread::SetThreadName(char* threadName) { strncpy(m_ThreadName, threadName, strlen(threadName)); } char* CThread::GetThreadName() { return m_ThreadName; } //執行緒互斥鎖 class CThreadMutex: public CLockObject { private: CRITICAL_SECTION m_CritSec;//臨界區 public: CThreadMutex(); ~CThreadMutex(); BOOL Lock();//加鎖,阻塞式 BOOL UnLock();//解鎖 BOOL TryLock();//加鎖,非阻塞式 }; CThreadMutex::CThreadMutex() { #if (_WIN32_WINNT >= 0x0403) //使用 InitializeCriticalSectionAndSpinCount 可以提高效能 ::InitializeCriticalSectionAndSpinCount(&m_CritSec,4000); #else ::InitializeCriticalSection(&m_CritSec); #endif } CThreadMutex::~CThreadMutex() { ::DeleteCriticalSection(&m_CritSec); } BOOL CThreadMutex::Lock() { ::EnterCriticalSection(&m_CritSec); return TRUE; } BOOL CThreadMutex::UnLock() { ::LeaveCriticalSection(&m_CritSec); return TRUE; } BOOL CThreadMutex::TryLock() { BOOL bRet = TryEnterCriticalSection(&m_CritSec); return bRet; } //條件變數 class CThreadCondition { private: HANDLE m_phEvent; //控制代碼 public: CThreadCondition(); ~CThreadCondition(); void Wait(); void Signal(); }; CThreadCondition::CThreadCondition() { //第二個引數 bManualReset FALSE the system automatically resets the state to nonsignaled //If this parameter is TRUE, the function creates a manual-reset event object //第三個引數 bInitialState FALSE it is nonsignaled m_phEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL); } CThreadCondition::~CThreadCondition() { if (NULL != m_phEvent) { ::CloseHandle((m_phEvent)); } } void CThreadCondition::Wait() { //If dwMilliseconds is INFINITE, the function will return only when the object is signaled. WaitForSingleObject(m_phEvent, INFINITE); ResetEvent(m_phEvent); } void CThreadCondition::Signal() { //Sets the specified event object to the signaled state SetEvent(m_phEvent); } //執行緒池類,主要負責排程執行緒,建立執行緒,刪除執行緒 class CThreadPool { friend class CWorkerThread; private: unsigned int m_nMaxNum; //當前執行緒池中所允許併發存在的執行緒的最大數目 unsigned int m_nAvailLow; //當前執行緒池中所允許存在的空閒執行緒的最小數目 //如果空閒數目低於該值,表明負載可能過重,此時有必要增加空閒執行緒池的數目 //實現中我們總是將執行緒調整為m_InitNum個 unsigned int m_nAvailHigh;//當前執行緒池中所允許的空閒的執行緒的最大數目, //如果空閒數目高於該值,表明當前負載可能較輕,此時將刪除多餘的空閒執行緒,刪除後調整數也為m_InitNum個 unsigned int m_nCurIdleThreadsNum;//當前執行緒池中實際存在的執行緒的個數,其值介於m_nAvailHigh和m_nAvailLow之間 //如果執行緒的個數始終維持在m_nAvailLow和m_nAvailHigh之間,則執行緒既不需要建立,也不需要刪除,保持平衡狀態 unsigned int m_nInitThreadsNum;//初始建立時執行緒池中的執行緒的個數 protected: CWorkerThread* GetIdleThread(void);//獲取空閒執行緒 void AppendToIdleList(CWorkerThread* jobthread);//執行緒加入空閒佇列 void MoveToBusyList(CWorkerThread* idlethread);//執行緒加入忙碌佇列 void MoveToIdleList(CWorkerThread* busythread);//執行緒加入空閒佇列 void DeleteIdleThread(int num); //刪除空閒執行緒 void CreateIdleThread(int num); //建立空閒執行緒 public: CThreadMutex m_BusyMutex;//when visit busy list,use m_BusyMutex to Lock and unlock CThreadMutex m_IdleMutex;//when visit idle list,use m_IdleMutex to Lock and unlock CThreadMutex m_ThreadNumMutex;//變數鎖, 目前用在m_nCurIdleThreadsNum修改上面 CThreadCondition m_BusyCond; //m_BusyCond is used to sync busy thread list CThreadCondition m_IdleCond; //m_IdleCond is used to sync idle thread list CThreadCondition m_MaxNumCond;//m_MaxNumCond is used to sync m_nCurIdleThreadsNum vector<CWorkerThread*> m_vecAllThreads;//所有創建出來的執行緒集合 vector<CWorkerThread*> m_vecBusyThreads;//忙碌執行緒佇列,隨著負載的多少會改變 vector<CWorkerThread*> m_vecIdleThreads;//空閒執行緒佇列,隨著負的多少會改變 public: void SetMaxNum(int maxnum){m_nMaxNum = maxnum;} //設定執行緒池執行的最大執行緒數 int GetMaxNum(void){return m_nMaxNum;} void SetAvailLowNum(int minnum){m_nAvailLow = minnum;} //設定最少空閒執行緒數 int GetAvailLowNum(void){return m_nAvailLow;} void SetAvailHighNum(int highnum){m_nAvailHigh = highnum;} //設定最多空閒執行緒數 int GetAvailHighNum(void){return m_nAvailHigh;} int GetCurIdleThreadsNum(void){return m_nCurIdleThreadsNum;} //獲取當前空閒執行緒個數 int GetAllThreadsNum(void){return m_vecAllThreads.size();} //獲取所有執行緒個數 int GetBusyThreadsNum(void){return m_vecBusyThreads.size();} //獲取忙碌空閒執行緒個數 void SetInitNum(int initnum){m_nInitThreadsNum = initnum;} int GetInitNum(void){return m_nInitThreadsNum;} CThreadPool(); ~CThreadPool(); CThreadPool(int initnum); void TerminateAll(); void Run(CJob* job,void* jobdata); }; //真正的工作執行緒,執行操作的執行緒 class CWorkerThread : public CThread { private: CThreadPool* m_pThreadPool;//執行緒池 CJob* m_pJob;//任務 void* m_pJobData;//任務引數 CThreadMutex m_VarMutex;// public: CThreadCondition m_JobAddCond; //有新的任務時觸發條件變數,每個執行緒一個條件變數,可以指定執行緒去執行任務 CThreadMutex m_WorkMutex;// CWorkerThread(); virtual ~CWorkerThread(); void Run(); void AddNewJob(CJob* job,void* jobdata); CJob* GetJob(void){return m_pJob;} void SetThreadPool(CThreadPool* thrpool); CThreadPool* GetThreadPool(void){return m_pThreadPool;} void Terminate(void); }; void CWorkerThread::Terminate(void) { //工作執行緒再處理任務結束才會解鎖,這個時候再去退出執行緒,避免打斷執行緒處理任務。 m_WorkMutex.Lock(); SetExitFlag(TRUE); //工作為假 代表要求執行緒退出 m_pJob = NULL; m_pJobData = NULL; printf("thread [%d] ready to exit\n", GetThreadID()); m_JobAddCond.Signal(); m_WorkMutex.UnLock(); WaitForSingleObject(GetThreadHandle(), INFINITE); CloseHandle(GetThreadHandle()); } CWorkerThread::CWorkerThread() { m_pJobData = NULL; m_pJob = NULL; m_pThreadPool = NULL; } CWorkerThread::~CWorkerThread() { if (NULL != m_pJob) {delete m_pJob; m_pJob = NULL;} if (NULL != m_pThreadPool) {delete m_pThreadPool; m_pThreadPool = NULL;} } void CWorkerThread::Run() { printf("Enter CWorkerThread::Run\n"); SetThreadState(THREAD_RUNNING); for(;;) { //當前執行緒不退出才需要等待任務的到來 while ((NULL == m_pJob) && !NeedExit()) { printf("thread [%d] wait for job \n", GetThreadID()); m_JobAddCond.Wait(); } if (NULL == m_pJob) { printf("thread [%d] exitFlag [%d]\n", GetThreadID(), NeedExit()); if (NeedExit()) { break;//不再等待任務,退出執行緒 } else { //任務為NULL 但不是執行緒退出,跳過這個任務 printf("m_pJob [%p] exitFlag [%d]\n", m_pJob, NeedExit()); continue; } } m_WorkMutex.Lock(); printf("thread [%d] accept the job [%d]\n", GetThreadID(), m_pJob->GetJobNo()); //真正執行任務的地方 m_pJob->Execute(m_pJobData); m_pJob->SetWorkThread(NULL); m_pJob = NULL; m_pJobData = NULL; m_pThreadPool->MoveToIdleList(this); SetThreadState(THREAD_IDLE); if(m_pThreadPool->m_vecIdleThreads.size() > m_pThreadPool->GetAvailHighNum()) { m_pThreadPool->DeleteIdleThread(m_pThreadPool->m_vecIdleThreads.size() - m_pThreadPool->GetInitNum()); } m_WorkMutex.UnLock(); } printf("thread [%d] exit\n", GetThreadID()); } void CWorkerThread::AddNewJob(CJob* pJob,void* jobdata) { assert(NULL != pJob); m_VarMutex.Lock(); m_pJob = pJob; m_pJobData = jobdata; pJob->SetWorkThread(this); m_VarMutex.UnLock(); printf("job [%d] add to the pool\n",m_pJob->GetJobNo()); m_JobAddCond.Signal(); } void CWorkerThread::SetThreadPool(CThreadPool* thrpool) { m_VarMutex.Lock(); m_pThreadPool = thrpool; m_VarMutex.UnLock(); } CThreadPool::CThreadPool() { m_nMaxNum = 50; m_nAvailLow = 5; m_nInitThreadsNum = 10; m_nCurIdleThreadsNum = 10; m_nAvailHigh = 20; m_vecBusyThreads.clear(); m_vecIdleThreads.clear(); int i; for (i=0; i<m_nInitThreadsNum; ++i) { CWorkerThread* pNewWorkThread = new CWorkerThread; pNewWorkThread->SetThreadPool(this); AppendToIdleList(pNewWorkThread); pNewWorkThread->Start(); } } CThreadPool::CThreadPool(int initnum) { m_nMaxNum = 30; m_nAvailLow = (initnum-10>0)?(initnum-10):3; m_nInitThreadsNum = m_nCurIdleThreadsNum = initnum ; m_nAvailHigh = initnum+10; m_vecAllThreads.clear(); m_vecBusyThreads.clear(); m_vecIdleThreads.clear(); int i; for (i=0; i<m_nInitThreadsNum; ++i) { CWorkerThread* pNewWorkThread = new CWorkerThread; pNewWorkThread->SetThreadPool(this); AppendToIdleList(pNewWorkThread); pNewWorkThread->Start(); } printf("CThreadPool::CThreadPool: Create Thread [%d] success\n", m_nInitThreadsNum); } CThreadPool::~CThreadPool() { TerminateAll(); } void CThreadPool::TerminateAll() { int i; for (i=0; i<m_vecAllThreads.size(); ++i) { CWorkerThread* pWorkThread = m_vecAllThreads[i]; pWorkThread->Terminate(); } } //獲取空閒的執行緒 CWorkerThread* CThreadPool::GetIdleThread(void) { while (0 == m_vecIdleThreads.size()) { printf("no idle threads, must wait\n"); m_IdleCond.Wait(); } m_IdleMutex.Lock(); if (0 < m_vecIdleThreads.size()) { CWorkerThread* pIdleThread = (CWorkerThread*)m_vecIdleThreads.front(); printf("get idle thread %d \n", pIdleThread->GetThreadID()); m_IdleMutex.UnLock(); return pIdleThread; } m_IdleMutex.UnLock(); printf("warning: no idle threads return\n"); return NULL; } //add an idle thread to idle list void CThreadPool::AppendToIdleList(CWorkerThread* jobthread) { m_IdleMutex.Lock(); m_vecIdleThreads.push_back(jobthread); m_vecAllThreads.push_back(jobthread); m_IdleMutex.UnLock(); } //move and idle thread to busy thread void CThreadPool::MoveToBusyList(CWorkerThread* idlethread) { m_BusyMutex.Lock(); m_vecBusyThreads.push_back(idlethread); m_nCurIdleThreadsNum--; m_BusyMutex.UnLock(); m_IdleMutex.Lock(); vector<CWorkerThread*>::iterator pos; pos = find(m_vecIdleThreads.begin(),m_vecIdleThreads.end(),idlethread); if(pos != m_vecIdleThreads.end()) { m_vecIdleThreads.erase(pos); } m_IdleMutex.UnLock(); } void CThreadPool::MoveToIdleList(CWorkerThread* busythread) { m_IdleMutex.Lock(); m_vecIdleThreads.push_back(busythread); m_nCurIdleThreadsNum++; m_IdleMutex.UnLock(); m_BusyMutex.Lock(); vector<CWorkerThread*>::iterator pos; pos = find(m_vecBusyThreads.begin(),m_vecBusyThreads.end(),busythread); if(pos!=m_vecBusyThreads.end()) m_vecBusyThreads.erase(pos); m_BusyMutex.UnLock(); m_IdleCond.Signal(); m_MaxNumCond.Signal(); } //create num idle thread and put them to idlelist void CThreadPool::CreateIdleThread(int num) { int i; for (i=0;i<num;i++) { CWorkerThread* pWorkThread = new CWorkerThread(); pWorkThread->SetThreadPool(this); AppendToIdleList(pWorkThread); m_ThreadNumMutex.Lock(); m_nCurIdleThreadsNum++; m_ThreadNumMutex.UnLock(); pWorkThread->Start();//begin the thread,the thread wait for job } } void CThreadPool::DeleteIdleThread(int num) { printf("Enter into CThreadPool::DeleteIdleThread\n"); m_IdleMutex.Lock(); printf("Delete Num is %dn",num); int i; for(i=0;i<num;i++) { CWorkerThread* thr; if(m_vecIdleThreads.size() > 0 ) { thr = (CWorkerThread*)m_vecIdleThreads.front(); printf("Get Idle thread %dn",thr->GetThreadID()); } else { printf("no idle thread, no need to delete thread\n"); break; } vector<CWorkerThread*>::iterator pos; pos = find(m_vecIdleThreads.begin(),m_vecIdleThreads.end(),thr); if(pos!=m_vecIdleThreads.end()) m_vecIdleThreads.erase(pos); m_nCurIdleThreadsNum--; printf("The idle thread available num:%d n",m_nCurIdleThreadsNum); printf("The idlelist num:%d n",m_vecIdleThreads.size()); } m_IdleMutex.UnLock(); } void CThreadPool::Run(CJob* job, void* jobdata) { assert(NULL != job); //if the busy thread num adds to m_nMaxNum,so we should wait if(m_nMaxNum <= GetBusyThreadsNum()) { printf("busy threads beyond the max threads number in the pool, must wait for idle threads\n"); m_MaxNumCond.Wait(); } //負載過重,空閒執行緒少,需要建立新的執行緒, 使其數目達到m_InitNum if(m_vecIdleThreads.size() < m_nAvailLow) { if(GetAllThreadsNum()+m_nInitThreadsNum-m_vecIdleThreads.size() < m_nMaxNum ) { //當前有m_vecIdleThreads.size()空閒執行緒, 另外再建立m_nInitThreadsNum - m_vecIdleThreads.size(), 當前總的空閒執行緒為m_nInitThreadsNum CreateIdleThread(m_nInitThreadsNum - m_vecIdleThreads.size()); } else { CreateIdleThread(m_nMaxNum - GetAllThreadsNum()); } } CWorkerThread* pWorkthread = GetIdleThread(); if(NULL != pWorkthread) { pWorkthread->m_WorkMutex.Lock(); MoveToBusyList(pWorkthread); pWorkthread->SetThreadPool(this); job->SetWorkThread(pWorkthread); printf("Job [%d] bind to thread [%d] \n", job->GetJobNo(), pWorkthread->GetThreadID()); pWorkthread->AddNewJob(job, jobdata); pWorkthread->m_WorkMutex.UnLock(); } else { printf("impossible to going here\n"); } } //執行緒管理類 class CThreadManage { public: CThreadManage(); CThreadManage(int num); virtual ~CThreadManage(); void Run(CJob* pjob, void* pJobData);//執行任務 void TerminateAll(); //停止所有的執行緒 private: int m_nNumOfThread; //初始時允許建立的最大的執行緒個數 CThreadPool* m_pPool;//實際的執行緒池 }; CThreadManage::CThreadManage() { m_nNumOfThread = 10; m_pPool = new CThreadPool(m_nNumOfThread); } CThreadManage::CThreadManage(int num) { m_nNumOfThread = num; m_pPool = new CThreadPool(m_nNumOfThread); } CThreadManage::~CThreadManage() { if (NULL != m_pPool) { delete m_pPool; m_pPool = NULL; } } void CThreadManage::Run(CJob* pjob, void* pJobData) { m_pPool->Run(pjob, pJobData); } void CThreadManage::TerminateAll() { m_pPool->TerminateAll(); } class myjob : public CJob { public: myjob(){} myjob(int i){SetJobNo(i);} ~myjob(){} void Execute(void* jobdata) { printf("The Job comes from CXJOB\n"); ::Sleep(2); } }; #if 0 int main() { CThreadManage* manage = new CThreadManage(50); for(int i=0;i<1000;i++) { myjob* job = new myjob(i); manage->Run(job, NULL); } ::Sleep(2); myjob* job = new myjob(); manage->Run(job, NULL); manage->TerminateAll(); return 0; } #endif
相關推薦
[C++][執行緒池][完整實現] 轉:執行緒池原理及建立(C++實現)
文章的主要框架是參考這篇文件的,http://jacky-dai.iteye.com/blog/1090285, 關於作者 張中慶,西安交通大學軟體所,在讀碩士,目前研究方向為分散式網路與移動中介軟體,對Linux極其愛好,可以通過[email protecte
C# winform框架 音樂播放器開發 聯網下載音樂功能的實現原理及原始碼(純原創--)
首先 ,我做下載音樂功能;主要是為了探究它是怎麼實現的;所以介面很醜,不要在意哈---- 接下來進入正題: 1.首先: 介面中下載音樂的部分主要是由3個segment組成:: 一個textbox,用於輸入比如你喜歡的歌曲名/歌手;; 第二個是button1 這是主
運維老司機帶你出坑:複雜故障的排查及解決(案例實錄)
sockets: used:已使用的所有協議套接字總量 TCP:inuse:正在使用(正在偵聽)的TCP套接字數量。其值≤ netstat –lnt | grep ^tcp | wc –l TCP:orphan:無主(不屬於任何程序)的TCP連線數(無用、待銷燬的TCP socket數) TCP:tw:等待關
Java併發(十八):阻塞佇列BlockingQueue BlockingQueue(阻塞佇列)詳解 二叉堆(一)之 圖文解析 和 C語言的實現 多執行緒程式設計:阻塞、併發佇列的使用總結 Java併發程式設計:阻塞佇列 java阻塞佇列 BlockingQueue(阻塞佇列)詳解
阻塞佇列(BlockingQueue)是一個支援兩個附加操作的佇列。 這兩個附加的操作是:在佇列為空時,獲取元素的執行緒會等待佇列變為非空。當佇列滿時,儲存元素的執行緒會等待佇列可用。 阻塞佇列常用於生產者和消費者的場景,生產者是往佇列裡新增元素的執行緒,消費者是從佇列裡拿元素的執行緒。阻塞佇列就是生產者
Java併發(二十一):執行緒池實現原理 Java併發(十八):阻塞佇列BlockingQueue Java併發(十八):阻塞佇列BlockingQueue Java併發程式設計:執行緒池的使用
一、總覽 執行緒池類ThreadPoolExecutor的相關類需要先了解: (圖片來自:https://javadoop.com/post/java-thread-pool#%E6%80%BB%E8%A7%88) Executor:位於最頂層,只有一個 execute(Runnab
多執行緒面試題和答案:執行緒鎖+執行緒池+執行緒同步
多執行緒面試題和答案:執行緒鎖+執行緒池+執行緒同步 1、併發程式設計三要素? 2、多執行緒的價值? 3、建立執行緒的有哪些方式?區別是什麼? 4、建立執行緒的三種方式的對比? 4、執行緒的生命週期及五種基本狀態及轉換條件 1、J
Java多執行緒高併發知識點二:執行緒池和CountDownLatch
執行緒池 池化是在為了複用常用的一種技術解決思路,比如連線池、執行緒池等,執行緒池主要是為了降低執行緒建立和銷燬造成的資源消耗,進而起到解決系統資源,提高系統相應速度的目的。Java中的ThreadPoolExecutor是JDK為我們提供好的執行緒池工具。
轉:如何在Vue項目中使用vw實現移動端適配
作用 -html res 尺寸 3.3 常用 css user 復用 https://www.w3cplus.com/mobile/vw-layout-in-vue.html 有關於移動端的適配布局一直以來都是眾說紛紜,對應的解決方案也是有很多種。在《使用Flexibl
(四)多執行緒說學逗唱:執行緒險惡,變數和執行緒安全不得不防
(一)多執行緒說學逗唱:關於執行緒那不得不說的二三事 (二)多執行緒說學逗唱:新手村偶遇Thread類 (三)多執行緒說學逗唱:村口的老R頭是個掃地僧(Runnable) 出了新手村,以後的路可就不那麼好走了,到底現在也是個江湖人,都必須經歷點困難挫折,要不以後拿什
演算法題:最長迴文子串(C#實現)
給定一個字串 s,找到 s 中最長的迴文子串。你可以假設 s 的最大長度為 1000。 示例 1: 輸入: "babad" 輸出: "bab" 注意: "aba" 也是一個有效答案。 示例 2: 輸入: "cbbd" 輸出: "bb
LinuxC多執行緒程式設計第五篇:執行緒通訊(Condition)
執行緒同步還有一種情況,執行緒1需要等某個條件成立才能繼續往下執行,如果這個條件不成立,執行緒1就阻塞等待,執行緒2在執行某個條件成立了就喚醒執行緒1。這個和Java中的wait()和notify()其實是一樣的 初始化與銷燬通訊條件 #include &
[.Net執行緒處理系列]專題五:執行緒同步——事件構造
引言: 其實這部分內容應該是屬於專題四,因為這篇也是講關於執行緒同步的,但是由於考慮到使用者的閱讀習慣問題,因為文章太長了,很多人不是很願意看包括我也是這樣的,同時也有和我說可以把程式碼弄成摺疊的,這樣就不會太長的,但是我覺得這樣也不怎麼便於閱讀,因為我
執行緒基礎:多工處理——Fork/Join框架(基本使用)
1. 概述在進行系統儲存專題的學習、總結、整理和寫作的過程中感覺有點累了,加上最近在做書稿的第二次校稿工作,系統儲存專題的學習和寫作進度明顯有些滯後,特別是編寫的Ceph MON知識點。所以後續1、2個月的時間打算換一個學習整理方向,之後再繼續恢復系統儲存專題的寫作。換一個什
轉置矩陣的分塊並行乘法(C語言實現),計算矩陣C[rawn][rawn]=A[rawm][rawn]'*B[rawm][rawn],子塊大小為S*T,其演算法實現原理參加本程式碼的附件。
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> #define rawm 4 #define rawn 4 #defi
Java入門系列之執行緒池ThreadPoolExecutor原理分析思考(十五)
前言 關於執行緒池原理分析請參看《http://objcoding.com/2019/04/25/threadpool-running/》,建議對原理不太瞭解的童鞋先看下此文然後再來看本文,這裡通過對原理的學習我談談對執行緒池的理解,若有錯誤之處,還望批評指正。 執行緒池思考 執行緒池我們可認為是準備好執行應
防雪崩利器:熔斷器 Hystrix 的原理與使用(轉)
ring bug 導致 運行 ade 新的 not metrics exceptio https://segmentfault.com/a/1190000005988895 前言 分布式系統中經常會出現某個基礎服務不可用造成整個系統不可用的情況, 這種現象被稱為服務雪崩效應
隊列的實現及操作(C語言描述)
img tdi 定義數據 上一個 判斷 free 隊列的單鏈表 插入數據 尾指針 // 隊列的單鏈表實現 // 頭節點:哨兵作用,不存放數據,用來初始化隊列時使隊頭隊尾指向的地方 // 首節點:頭節點後第一個節點,存放數據 #include&
C++實現線性表的鏈接存儲結構(單鏈表)
mage pac lis ins 尾插 初始化 arr space ios 將線性表的抽象數據類型定義在鏈接存儲結構下用C++的類實現,由於線性表的數據元素類型不確定,所以采用模板機制。 1 頭文件linklist.h 2 #pragma once 3 #in
題目:最長回文子串(C++)
ptr 這位 優化 png 技術分享 ring tdi xen 回文 看到這個題第一反應是做過啊,然後就開始寫,等寫完一測。emmmmm,原來是最長回文子串不是最長回文子序列,但是寫都寫了,我就把代碼稍微修改了一下讓適應於該題目,代碼如下: static const au
轉:ubuntu 18.04 LTS 安裝 java10(JDK) 及問題說明
.net 需要 div ron etc profile lan .bashrc undefine 原文地址:ubuntu 18.04 LTS 安裝 java10 及問題說明 1.下載相應的安裝包,例如jdk-10.0.1_linux-x64_bin.tar.gz。下載地