Thread management class

本文介绍了一种线程管理类的设计思路,该类能够将线程函数与类成员函数连接起来,实现线程任务的有效管理和执行。通过使用ThreadLocal Storage (TLS)结构,解决了成员函数作为线程函数的问题,并提供了启动、停止线程的方法。

Well, multi thread is a useful mechanism in many scenarios. But the thread is not easy to control. Here I will discuss a thread management class which provides a connection between thread function and class member function.

 

A common question about the thread in a job interview is that can a class member function works as a thread function? The answer is definitely, but few people know why. The reason is: a non-static member function has an implicit parameter: this, so the prototype is not the same as the thread function.

 

The key point of the Thread management class is that the class separate the working function from the thread function, and implement it in a member function of another class.

 

Here is the implement of Thread management class:

 

The class IRunnable does the main work in the thread. You may derive a class from it with any attributes or parameters you want. The function run() will be called in thread.

// The core interface of this threading implementation.

class IRunnable {

    friend class CThread;

    friend class CSimpleThreadPool;

protected:

    virtual void run() = 0;

};

 

Here a TLS structure is used to communicate with classes, because the run() function and the StartThreadST() are in the same thread context, so they can access to the same TLS allocation, though they are from different classes.

// structure holds Thread Local Storage descriptor

struct TLSDescriptor {

    DWORD descriptor;

 

    TLSDescriptor() {

        descriptor = TlsAlloc();

        if (descriptor == -1) throw "TlsAlloc() failed to create descriptor";

    };

 

    ~TLSDescriptor() { TlsFree(descriptor); };

};

 

And the following is the thread management class.

When a variable is used as a controller to stop thread, it’s better to define the variable as a volatile one.

// Very basic thread class, implementing basic threading API

// the key point: separate the working function from thread function, and implement in a member function in other class.

class CThread: public IRunnable {

private:

    static TLSDescriptor m_TLSDesc;

    volatile bool   m_bIsInterrupted;  // control loop in thread

    volatile bool   m_bIsRunning;      // indicate if thread is running

 

    int             m_nThreadPriority;

    IRunnable       *m_RunObj;  // provide run function by other class

    QMutex          m_qMutex;   // notify weather the thread is running

 

    // This is the thread's API function to be executed. Method executes

    // run() method of the CThread instance passed as parameter.

    static DWORD WINAPI StartThreadST(LPVOID PARAM) {

        CThread *_this = (CThread *) PARAM;

 

        if (_this != NULL) {

            _this->m_qMutex.Lock();    // show the thread is running

 

            // Set the pointer to the instance of the passed CThread

            // in the current Thread's Local Storage.

            // Also seecurrentThread() method.

            TlsSetValue(CThread::m_TLSDesc.descriptor, (LPVOID) _this);

            _this->run();

            _this->m_bIsRunning = false;

            _this->m_qMutex.Unlock();  // notify run() returned

        }

        return 0;

    };

 

protected:

    // It is not possible to instantiate CThread objects directly. Possible only by

    // specifying a IRunnable object to execute its run() method.

    CThread(int nPriority = THREAD_PRIORITY_NORMAL): m_qMutex() {

        this->m_bIsInterrupted = false;

        this->m_bIsRunning = false;

        this->m_nThreadPriority = nPriority;

        this->m_RunObj = NULL;

    };

 

    // this implementation of the run() will execute the passed IRunnable

    // object (if not null). Inheriting class is responsible for using this

    // method or overriding it with a different one.

    virtual void run() {

        if (this->m_RunObj != NULL)

            this->m_RunObj->run();

    };

 

public:

    CThread(IRunnable *RunTask, int nPriority = THREAD_PRIORITY_NORMAL): m_qMutex() {

        this->m_bIsInterrupted = false;

        this->m_bIsRunning = false;

        this->m_nThreadPriority = nPriority;

 

        if (this != RunTask) this->m_RunObj = RunTask;

        else throw "Self referencing not allowed.";

    };

 

    virtual ~CThread() {

        this->interrupt();

        // wait until thread ends

        this->join();

    };

 

    // Method returns the instance of a CThread responsible

    // for the context of the current thread.

    // used only in thread function

    static CThread& currentThread() {

        CThread *thr = (CThread *) TlsGetValue(CThread::m_TLSDesc.descriptor);

        if (thr == NULL) throw "Call is not within a CThread context.";

        return *thr;

    };

 

    // Method signals thread to stop execution.

    void interrupt() { this->m_bIsInterrupted = true; };

 

    // Check if thread was signaled to stop.

    bool isInterrupted() { return this->m_bIsInterrupted; };

 

    // Method will wait for thread's termination.

    void join() {

        this->m_qMutex.Lock();

        this->m_qMutex.Unlock();

    };

 

    // Method starts the Thread. If thread is already started/running, method

    // will simply return.

    void start() {

        HANDLE  hThread;

        LPTHREAD_START_ROUTINE pStartRoutine = &CThread::StartThreadST;

 

        if (this->m_qMutex.TryLock()) {  // test if the thread is running

            if (!this->m_bIsRunning) {

                this->m_bIsRunning = true;

                this->m_bIsInterrupted = false;

 

                hThread = ::CreateThread(NULL, 0, pStartRoutine, (PVOID) this, 0, NULL);

                if (hThread == NULL) {

                   this->m_bIsRunning = false;

                    this->m_qMutex.Unlock();

                   throw "Failed to call CreateThread(). Thread not started.";

                }

 

                ::SetThreadPriority(hThread, this->m_nThreadPriority);

                ::CloseHandle(hThread);

            }

 

            this->m_qMutex.Unlock();

        }

    };

};

 

Steps to use the class.

Firstly device a class from IRunnable:

 

class Increase : public IRunnable

{

private:

    CEdit *m_pEdit;

public:

    Increase(CEdit *pEdit, CThread *pCThread = NULL) {

        m_pEdit = pEdit;

    };

    ~Increase() {};

 

    virtual void run()

    {

        HWND hWin = (AfxGetApp()->m_pMainWnd)->m_hWnd;

        int iIndex = 0;

 

        while (!CThread::currentThread().isInterrupted()) {

 

            PostMessage(hWin, MSG_DATA_INS, (WPARAM)m_pEdit, (LPARAM)iIndex);

            iIndex++;

            Sleep(1000);

        }

    };

};

 

Secondly attach the Increase class into CThread.

void CThreadClassTestDlg::OnBnClickedButton()

{

    Increase *pIncrease = NULL;

    pIncrease = new Increase(&this->m_CEdit);

 

    CThread *pCThread = NULL;

    pCThread = new CThread(pIncrease);

    if (NULL != pCThread)

        pCThread->start();

}

 

When want to stop the thread, just call.

pIncrease ->interrupt();

 

 

And the other way to use the thread class is derive from the CThread directly: class Increase : public CThread, and implement the virtual run()function.

The code is as followed:

void CThreadClassTestDlg::OnBnClickedButton()

{

    Increase *pIncrease = NULL;

    pIncrease = new Increase(&this->m_CEdit);

    if (NULL != pIncrease)

        pIncrease->start();                    

}

 

And with the class we can implement a light weighted thread pool, which I discuss later.

 

Thanks to the original author Ruslan Ciurca, from his source code I do learn a lot.

For more information please link to:

http://www.codeproject.com/KB/IP/IOCP_how_to_cook.aspx

Management Plugin TCP JAVA是一种用于管理和监控Java应用程序的工具。它通过TCP协议与Java应用程序进行通信,帮助管理员实时监控应用程序的性能、资源使用情况和运行状态。以下是关于Management Plugin TCP JAVA的一些详细介绍: ### 功能特点 1. **性能监控**:可以实时监控Java应用程序的CPU使用率、内存使用情况、线程活动等关键性能指标。 2. **日志管理**:提供集中化的日志管理功能,方便管理员查看和分析应用程序的日志信息。 3. **故障诊断**:帮助快速定位和解决应用程序中的问题,如内存泄漏、线程死锁等。 4. **配置管理**:支持动态调整应用程序的配置参数,无需重启应用即可生效。 5. **安全控制**:提供访问控制和权限管理功能,确保只有授权用户才能访问管理插件。 ### 工作原理 Management Plugin TCP JAVA通过在Java应用程序中嵌入一个轻量级的代理(Agent),该代理负责收集应用程序的运行数据并通过TCP协议发送给管理服务器。管理服务器接收到数据后,可以进行实时分析和展示,并提供相应的管理操作接口。 ### 使用场景 - **生产环境监控**:在生产环境中部署Management Plugin TCP JAVA,实时监控应用程序的性能和健康状态。 - **开发调试**:在开发和测试阶段,使用Management Plugin TCP JAVA进行性能调优和问题排查。 - **运维管理**:为运维团队提供统一的管理界面,简化对多个Java应用程序的管理和维护工作。 ### 示例代码 以下是一个简单的示例,展示如何在Java应用程序中集成Management Plugin TCP JAVA: ```java import java.lang.management.ManagementFactory; import javax.management.MBeanServer; import javax.management.ObjectName; public class MyApp { public static void main(String[] args) throws Exception { // 获取平台MBeanServer MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); // 注册自定义MBean MyMBean myMBean = new MyMBeanImpl(); ObjectName name = new ObjectName("com.example:type=MyMBean"); mbs.registerMBean(myMBean, name); // 保持应用程序运行 while (true) { Thread.sleep(1000); } } } interface MyMBean { int getValue(); void setValue(int value); } class MyMBeanImpl implements MyMBean { private int value; @Override public int getValue() { return value; } @Override public void setValue(int value) { this.value = value; } } ``` ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值