1. 程式人生 > >C++多執行緒程式設計(執行緒類)

C++多執行緒程式設計(執行緒類)

簡述

通過執行緒類來管理執行緒,實現業務邏輯與執行緒管理分離

原始碼

介面類 SFRunnable.h

class SFRunnable
{
    public:
        virtual ~SFRunnable() {};
        virtual void Run() = 0;
};

執行緒類 SFThread.h

#ifndef __SFTHREAD_H__
#define __SFTHREAD_H__

#include <string>
#include <windows.h>
#include <process.h>

#include "SFRunnable.h"
class SFThread : public SFRunnable { private: explicit SFThread(const SFThread & rhs);//explicit public: SFThread(); SFThread(SFRunnable * pRunnable); SFThread(const char * ThreadName, SFRunnable * pRunnable = NULL); SFThread(std::string ThreadName, SFRunnable * pRunnable = NULL); ~SFThread(void
); /** 開始執行執行緒 @arg bSuspend 開始執行時是否掛起 **/ bool Start(bool bSuspend = false); /** 執行的執行緒函式,可以使用派生類重寫此函式 **/ virtual void Run(); /** 當前執行此函式執行緒等待執行緒結束 @arg timeout 等待超時時間,如果為負數,等待無限時長 **/ void Join(int timeout = -1); /** 恢復掛起的執行緒 **/
void Resume(); /** 掛起執行緒 **/ void Suspend(); /** 終止執行緒的執行 **/ bool Terminate(unsigned long ExitCode); unsigned int GetThreadID(); std::string GetThreadName(); void SetThreadName(std::string ThreadName); void SetThreadName(const char * ThreadName); private: static unsigned int WINAPI StaticThreadFunc(void * arg);//執行緒處理函式 private: HANDLE m_handle;//執行緒控制代碼 SFRunnable * const m_pRunnable;//執行邏輯的指標 unsigned int m_ThreadID;//執行緒ID std::string m_ThreadName;//執行緒name volatile bool m_bRun;//執行緒是否執行 }; #endif /* volatile:A volatile specifier is a hint to a compiler that an object may change its value in ways not specified by the language so that aggressive optimizations must be avoided. */

SFThread.cpp

#include "SFThread.h"

SFThread::SFThread(void) : m_pRunnable(NULL),m_bRun(false)//進入建構函式之前 先初始化 成員變數 有一些成員變數 必須先初始化 比如常量什麼的
{
}

SFThread::~SFThread(void)
{
}

SFThread::SFThread(SFRunnable * pRunnable) : m_ThreadName(""),m_pRunnable(pRunnable),m_bRun(false)
{
}

SFThread::SFThread(const char * ThreadName, SFRunnable * pRunnable) : m_ThreadName(ThreadName),m_pRunnable(pRunnable),m_bRun(false)
{
}

SFThread::SFThread(std::string ThreadName, SFRunnable * pRunnable) : m_ThreadName(ThreadName),m_pRunnable(pRunnable),m_bRun(false)
{
}

bool SFThread::Start(bool bSuspend)
{
    if(m_bRun)
    {
        return true;
    }
    if(bSuspend)
    {
        m_handle = (HANDLE)_beginthreadex(NULL, 0, StaticThreadFunc, this, CREATE_SUSPENDED, &m_ThreadID);
    }
    else
    {
        m_handle = (HANDLE)_beginthreadex(NULL, 0, StaticThreadFunc, this, 0, &m_ThreadID);
    }
    m_bRun = (NULL != m_handle);
    return m_bRun;
}

void SFThread::Run()
{
    if(!m_bRun)//如果沒執行
    {
        return;
    }
    if(NULL != m_pRunnable)//如果控制代碼不為空
    {
        m_pRunnable->Run();
    }
    m_bRun = false;
}

void SFThread::Join(int timeout)
{
    if(NULL == m_handle || !m_bRun)
    {
        return;
    }
    if(timeout <= 0)
    {
        timeout = INFINITE;
    }
    ::WaitForSingleObject(m_handle, timeout);
}

void SFThread::Resume()
{
    if(NULL == m_handle || !m_bRun)
    {
        return;
    }
    ::ResumeThread(m_handle);
}

void SFThread::Suspend()
{
    if(NULL == m_handle || !m_bRun)
    {
        return;
    }
    ::SuspendThread(m_handle);
}

bool SFThread::Terminate(unsigned long ExitCode)
{
    if(NULL == m_handle || !m_bRun)
    {
        return true;
    }
    if(::TerminateThread(m_handle, ExitCode))
    {
        ::CloseHandle(m_handle);
        m_bRun  =   false;//設定執行緒的執行狀態為假
        return true;
    }
    return false;
}

unsigned int SFThread::GetThreadID()
{
    return m_ThreadID;
}

std::string SFThread::GetThreadName()
{
    return m_ThreadName;
}

void SFThread::SetThreadName(std::string ThreadName)
{
    m_ThreadName = ThreadName;
}

void SFThread::SetThreadName(const char * ThreadName)
{
    if(NULL == ThreadName)
    {
        m_ThreadName = "";
    }
    else
    {
        m_ThreadName = ThreadName;
    }
}

unsigned int SFThread::StaticThreadFunc(void * arg)
{
    SFThread * pThread = (SFThread *)arg;
    pThread->Run();
    return 0;
}

業務類 SFTimer.h

#ifndef SFTimer_H
#define SFTimer_H

#include<windows.h>
#include"SFThread.h"
#define WM_UPDATETIME WM_USER+101 //使用者訊息,每秒傳送一次。

class SFTimer:public SFRunnable
{
    private:
        HWND hwnd;
        int Day;
        int Hour;
        int Minute;
        int Second;

        void init();//初始化天、小時、分鐘、秒全部為零
        void CountDown();//倒計時
        void Time();//正計時
    public:
        SFTimer();
        SFTimer(HWND hwnd);

        int     getDay();
        void    setDay(int day);
        int     getHour();
        void    setHour(int hour);
        int     getMinute();
        void    setMinute(int minute);
        int     getSecond();
        void    setSecond(int second);

        void Run();
        void SendUploadTimeMessage();
};

#endif

SFTmier.cpp

#include "SFTimer.h"

SFTimer::SFTimer()
{
    this->init();
}

SFTimer::SFTimer(HWND hwnd)
{
    this->init();
    this->hwnd  =   hwnd;
}


int SFTimer::getDay()
{
    return this->Day;
}
void SFTimer::setDay(int day)
{
    this->Day   =   day;
}

int SFTimer::getHour()
{
    return this->Hour;
}
void SFTimer::setHour(int hour)
{
    this->Hour  =   hour;
}

int SFTimer::getMinute()
{
    return this->Minute;
}
void SFTimer::setMinute(int minute)
{
    this->Minute    =   minute;
}

int SFTimer::getSecond()
{
    return this->Second;
}
void SFTimer::setSecond(int second)
{
    this->Second    =   second;
}

void SFTimer::SendUploadTimeMessage()
{
    PostMessage(this->hwnd,WM_UPDATETIME,this->Minute,this->Second);
}
void SFTimer::init()
{
    this->Day       =   0;
    this->Hour      =   0;
    this->Minute    =   0;
    this->Second    =   0;
}
void SFTimer::CountDown()
{
    for(;this->Day>=0;this->Day--)//天迴圈
    {
        for(;this->Hour>=0;this->Hour--)//小時迴圈
        {


            for(; this->Minute >=0; this->Minute--)//分鐘迴圈
            {

                for(; this->Second >=0; this->Second--)//秒迴圈
                {
                    Sleep(1000);//Sleep看清楚間
                    this->SendUploadTimeMessage();//傳送訊息
                }
                this->Second = 59;
            }

        }
    }   
}

void SFTimer::Time()
{
    this->init();//初始化各個引數
    while(this->Minute<5)//5分鐘計時
    {
        this->Second+=1;
        if(this->Second >   60)
        {
            this->Second    =   0;
            this->Minute    +=  1;

            if(this->Minute >   60)
            {
                this->Minute    =   0;
                this->Hour  +=  1;
                if(this->Hour   >   60)
                {
                    this->Hour  =   0;
                    this->Day   +=1;
                }
            }
        }
        this->SendUploadTimeMessage();
        Sleep(1000);
    }
}

void SFTimer::Run()
{   
    this->CountDown();
    this->Time();
}

測試程式碼 testMain.cpp

#include <iostream>

using namespace std;

#include "SFTimer.h"
#include "SFThread.h"

int main(int argc, char *argv[])  
{  
    SFTimer*    timer   =   new SFTimer();//具體業務類

    timer->setDay(0);//設定天
    timer->setHour(0);//設定小時
    timer->setMinute(2);//設定分鐘
    timer->setSecond(0);//設定秒

    SFThread* thread    =   new SFThread(timer);//執行緒類
    thread->Start();//啟動執行緒

    while(1)
    {
        cout<<"計時開始:"<<timer->getMinute()<<"分"<<timer->getSecond()<<"秒"<<endl; 
        Sleep(1000);//Sleep看清楚間
        system("cls");
    }

    getchar();

    return 0;  
}

實現效果

如下圖所示:實現2分鐘倒計時,以及5分鐘正計時。
這裡寫圖片描述