`
konin
  • 浏览: 10251 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

如何完整的实现线程类

阅读更多

1.一般方法

    一般情况下,使用线程,是用pthread_create函数创建一个线程,创建的过程中采用传递函数指针的方式来实现主体的业务逻辑。比如

/*thread.c*/ 
#include <stdio.h> 
#include <pthread.h> 
 
/*线程一*/ 
void thread_1(void) 

    int i=0; 
    for(i=0;i<=6;i++) 
    { 
        printf("This is a pthread_1.\n"); 
        if(i==2) 
            pthread_exit(0); 
        sleep(1); 
    } 

 
/*线程二*/ 
void thread_2(void) 

    int i; 
    for(i=0;i<3;i++) 
        printf("This is a pthread_2.\n"); 
    pthread_exit(0); 

 
int main(void) 

    pthread_t id_1,id_2; 
    int i,ret; 
/*创建线程一*/ 
    ret=pthread_create(&id_1,NULL,(void  *) thread_1,NULL); 
    if(ret!=0) 
    { 
        printf("Create pthread error!\n"); 
    return -1; 
    } 
/*创建线程二*/ 
     ret=pthread_create(&id_2,NULL,(void  *) thread_2,NULL); 
    if(ret!=0) 
    { 
        printf("Create pthread error!\n"); 
    return -1; 
    } 
/*等待线程结束*/ 
    pthread_join(id_1,NULL); 
    pthread_join(id_2,NULL); 
    return 0; 

 在这以上这段代码中,首先实现了业务函数treahd_1等函数,再采用pthread_create函数创建线程,把函数指针传入,以便线程创建后调用函数。那么,在业务函数执行后,我们怎么判断线程有没有执行完呢(因为有时候,我们需要等待线程执行完后才能执行下一步的逻辑),通过函数ptread_join来判断。这几个函数的具体用法,可以百度。我们这里只讨论流程。

 

2.面向过程的方法

在上面的过程中,我们说道了普通的方法,如果采用面向对象的方法,该如何实现呢,有些人就说了,不就是进行封装嘛。。。不要忘记了。。。当你一旦调用pthread_create函数,就会立即调用你的业务函数pthread_1函数,封装的时候,如何先不执行业务函数呢?

 

第一步 完成一个纯虚函数,有什么用呢,让后面的线程类继承:

class IRunnable {
public:
    /**
     * 析构函数
     */
    virtual ~IRunnable() {}
   
    /**
     * 线程运行逻辑
     */
    virtual void run() = 0;
};

 

第二步,声明线程类

void* esRunThread(void* target) {
    try {
        reinterpret_cast<es::IRunnable*>(target)->run();
    } catch (es::SQLException& sqlEx) {
        cerr << "Uncaught exception in Thread::run(), " << sqlEx.what() << ", "
             << sqlEx.getSQLString() << endl;
    } catch (es::Exception& ex) {
        cerr << "Uncaught exception in Thread::run(), " << ex.what() << endl;
    } catch (...) {
        cerr << "Uncaught exception in Thread::run()" << endl;
    }
    return 0;
}

上面的代码,是把target进行类型转换为IRunnable,然后调用其run函数。

class Thread : public IRunnable{
public:

    typedef pthread_t ThreadId;

    Thread();

    Thread(IRunnable* target);

    virtual ~Thread();


    ThreadId getId() const;

 
    void start();

    void join();

    /**
     * 分离线程, 不允许等待已经join或detach过的线程
     */
    void detach();

    /**
     * 休眠线程
     * @param millis 休眠毫秒数
     */
    static void sleep(int millis);

    /**
     * 暂停当前线程让其它线程先运行
     */
    static void yield();


    static ThreadId getCurrentThreadId();

  
    virtual void run();

private:
    IRunnable*  _target;
    ThreadId    _id;
#endif
};

大家保持一点耐心,这里主要的函数是2个,一个 start,一个run。那么,看看这2个函数的实现

 

void Thread::start() {

    pthread_attr_t attr;
    int rc = pthread_attr_init(&attr);
    if (rc) {
        throw ThreadException(rc);
    }

    IRunnable* target = (_target ? _target : this);
    rc = pthread_create(&_id, &attr, ::esRunThread, target);
    if (rc) {
        throw ThreadException(errno);
    }
}

 

void Thread::run() {}

 

看到这里,大家看明白了吗?

这个Thread类,我们并不能直接拿来使用,为什么?因为他的run函数为空的,需要自己定义一个类,比如myThread来继承Thread,从而实现run函数。实现后,myThread.start()来启动该类。为什么start就能启动该类呢?

 

因为在start的过程中,创建了线程,参数当中传递的函数指针是esRunThread,函数的参数是target,而target实际上是用户自定实现的一个接口类(用来实现业务),如果没有实现该类,那么就默认为this(this实际就是用户自定义实现的线程类)。esRunThread函数把target强转后调用了run函数(用户实现的run函数),那么整个线程类的实现过程就完成了。

 

问大家一个小问题,如何保证让thread 不能被赋值拷贝?也就是防止pthread1=ptread2  ??

 

 

0
2
分享到:
评论

相关推荐

    创建线程类轻松实现线程管理

    Java作为多线程编程的强大语言,提供了多种创建线程的方法,其中一种是通过创建线程类来实现。本文将深入探讨如何创建线程类以及如何进行线程管理,帮助你轻松掌握这一核心技能。 首先,我们来看看如何在Java中创建...

    thread 线程类 实现runnable接口

    "Thread 线程类实现 Runnable 接口" Thread 线程类是 Java 中 Thread 和 Runnable 接口的实现,它提供了线程的基本操作和管理。下面是对 Thread 类的详细介绍: 1. Runnable 接口 Runnable 接口是 Thread 类的...

    使用内部类实现线程

    当我们谈论使用内部类实现线程时,通常指的是非静态内部类(也称为成员内部类),因为它们能直接访问外部类的所有成员,包括私有变量和方法,这对于创建线程并与其关联的数据共享非常方便。 首先,让我们看看如何...

    c++线程类代码实现

    - **virtual void Run()**:重写父类的纯虚函数,具体实现线程运行时的行为。 4. **Join()** - **void Join(int timeout = -1)**:等待线程结束或超时。如果`timeout`为负数,则无限期等待。 5. **Resume()** -...

    线程封装类

    在编程领域,线程是操作系统分配CPU执行时间的基本单元,...在提供的文件列表中,"线程"可能是包含这个封装线程类的源代码文件,你可以通过查看和学习这个类的实现,进一步理解如何在VC++环境中有效地管理和控制线程。

    MFC同步线程类

    总结来说,MFC的同步线程类为C++开发者提供了丰富的功能,用于创建和管理线程,以及实现线程间的安全同步。理解并熟练使用这些类,可以极大地提升多线程应用程序的稳定性和效率。在实际开发中,应根据具体需求选择...

    JAVA多线程类QQ简单实现

    在本项目中,“JAVA多线程类QQ简单实现”是一个基于客户端-服务器架构的QQ聊天应用的简化版本,它利用了JAVA编程语言的核心特性——多线程,来处理并发的网络通信。王刚老师的“疯狂JAVA”系列教程是这个项目的灵感...

    易语言创建类线程

    在易语言中,通常会定义一个类,然后在类中实现线程函数。当调用启动类线程的函数或方法时,易语言会创建一个新的线程实例,并在该线程上执行类中定义的线程函数。 "关闭类线程"是指结束某个类线程的执行。在某些...

    C++封装的一个跨平台的线程类和锁类

    3. **同步机制**:线程类可能会包含同步原语,如条件变量、信号量或互斥锁,以实现线程间的通信和协作。 4. **线程退出**:当线程执行完毕或被显式停止时,线程类需要有一个优雅的退出机制,这可能涉及到线程状态的...

    易语言多线程类

    通过创建和使用多线程类,开发者可以将复杂的任务分解成若干个独立的线程,每个线程负责一部分工作,从而实现任务的并行处理。这样不仅可以充分利用多核处理器的计算能力,还能提高程序的执行效率,尤其是在处理大量...

    C++实现的可以安全的暂停、继续、停止线程的线程类和Sample

    在使用线程时,最麻烦的就是线程的同步控制,如... 本人经过试验和总结,整理出可以安全的进行暂停、继续、停止线程执行的一个线程类,能非常方便的对线程进行控制。 附件里是源码和Sample程序,并有详细的使用说明。

    利用VB6实现多线程

    通常,我们会创建一个类模块(Class Module),然后在这个类模块中定义线程函数,如`Public Sub ThreadFunction()`,并在其中实现需要并发执行的任务。 4. 调用线程 在主应用程序中,可以通过创建ActiveX EXE的...

    MFC封装的线程类

    本文将深入探讨如何利用MFC封装的线程类来实现多线程编程。 首先,MFC中的线程类是`CWinThread`,它是所有线程的基础类。如果你想要创建一个新的线程,你需要继承`CWinThread`并重写其中的关键成员函数。描述中提到...

    自定义Dictionary类如何在类内实现线程同步

    自定义Dictionary类如何在类内实现线程同步自定义Dictionary类如何在类内实现线程同步自定义Dictionary类如何在类内实现线程同步自定义Dictionary类如何在类内实现线程同步自定义Dictionary类如何在类内实现线程同步...

    java实现多线程文件传输

    7. **线程间通信**:使用`BlockingQueue`或`Future`可以实现线程间的通信,例如,一个线程负责读取文件块并放入队列,另一个线程从队列中取出并发送。 8. **性能调优**:合理设置线程池大小、考虑使用NIO(非阻塞I/...

    【java学习记录】11.多线程实现阶乘计算(Thread类和Runnable接口)

    本篇文章将深入探讨如何利用`Thread`类和`Runnable`接口来实现阶乘计算的多线程解决方案。阶乘计算是数学中的一个概念,对于非负整数n,其阶乘表示为所有小于等于n的正整数的乘积,记作n!。 首先,我们来看如何使用...

    C#实现支持断点续传多线程下载客户端工具类

    在C#编程中,实现一个支持断点续传和多线程下载的HTTP Web客户端工具类是一项复杂但实用的任务。断点续传允许用户在下载过程中中断,然后在稍后的时间点继续下载,而不会丢失已下载的数据。多线程下载则能显著提高大...

    易语言源码多线程类源码.rar

    2. 易语言中的线程类:易语言提供了内置的线程类,开发者可以通过创建线程对象,定义线程函数(即线程执行的代码块),然后启动线程来实现多线程。线程类通常包含创建、启动、同步和销毁线程的方法。 3. 线程同步:...

    VC中利用多线程技术实现线程之间的通信

    本文将深入探讨如何在VC++中利用多线程技术来实现线程间的通信。 首先,创建线程是多线程编程的第一步。在VC++中,可以通过`CreateThread`函数或`_beginthreadex`函数来创建新线程。创建线程时,需要提供一个函数...

    线程管理工具类

    1. `ThreadManager`类,实现线程管理功能,包括一个静态成员变量`defaultInstance`来存储单例实例。 2. 单例的获取方法,使用双重检索模式,例如`getDefault()`方法。 3. `Builder`类,作为建造者模式的一部分,提供...

Global site tag (gtag.js) - Google Analytics