废话不多说,详细介绍使用线程的优点好处请参考baidu、google。
一、线程使用场景。使用线程的方式大致有两种:
(1)流水线方式。根据业务特点,将一个流程的处理分割成多个线程,形成流水线的处理方式。产生的结果:延长单一流程的处理时间,提高系统整体的吞吐能力。
(2)线程池方式。针对处理时间比较长且没有内蕴状态的线程,使用线程池方式分流消息,加快对线程消息的处理,避免其成为系统瓶颈。
线程使用的关键是 线程消息队列、线程锁、智能指针 的 使用。其中以线程消息队列最为重要。

二、线程消息队列描述。所谓线程消息队列,就是一个普通的循环队列(其它数据结构也未尝不可,具体内容请参考数据结构课本)加上“多生产者-单(多)消费者的PV操作”(详细内容请参考操作系统课本)。流水线方式中的线程是单消费者,线程池方式中的线程是多消费者。
为了后文更好的描述问题,作如下说明:
(1)假定循环队列CircleQueue中,存放的消息指针类型是MyMSG *,入队操作EnQueue,出队操作DeQueue,判断队满IsQueueFull,判断队空IsQueueEmpty。
(2)生产者消费者:生产者线程生产消息(MyMSG *),放在一个空缓冲区(CircleQueue)中,供消费者线程消费,生产者生产消息(EnQueue),如果缓冲区满(IsQueueFull),则被阻塞,消费者消费消息(DeQueue),如果缓冲区空(IsQueueEmpty),则被阻塞。线程消息队列就是生产者消费者问题中的缓冲区,而它的生产者是不限定的,任何线程都可以作为生产者向其中进行EnQueue操作,消费线程则可能是一个,也可能是多个。因此对循环队列的任何操作都要加锁,以保证线程安全。
PV操作和锁机制的基础都是信号量。下面列出posix标准中给出的有关信号量的操作:

#include <semaphore.h>
int sem_init(sem_t *sem, int pshared, unsigned int value);
int sem_wait(sem_t * sem);
int sem_trywait(sem_t * sem);
int sem_post(sem_t * sem);
int sem_getvalue(sem_t * sem, int * sval);
int sem_destroy(sem_t * sem);

各个函数的详细用法,请在linux/unix上查看man。

三、线程消息队列实现。基于以上讨论,下面给出线程消息队列的实现(仅为了说明问题,非标准可运行代码)。

class ThreadQueue
{
    CircleQueue 
* queue;
    
int nFull;
    
int nEmpty;
    sem_t lock;
    sem_t fullCond;
    sem_t emptyCond
}
;
void createThreadQueue()
{
    createCircleQueue(queue);
    nFull
=0;
    nEmpty
=0;
    sem_ini(
&lock,0,1);
    sem_init(
&fullCond,0,0);
    sem_init(
&emptyCond,0,0);
}

void putq(MyMSG * msg)
{
    sem_wait(
&lock);
    
if(IsQueueFull(queue))
    
{
        nFull
++;
        sem_post(
&lock);
        sem_wait(
&fullCond);
        sem_wait(
&lock);
        nFull
--;
    }

    EnQueue(queue,msg);
    
if(nEmpty>0)
    
{
        sem_post(
&emptyCond);
    }

    sem_post(
&lock);
}

void getq(MyMSG * msg)
{
    sem_wait(
&lock);
    
if(IsQueueEmpty(queue))
    
{
        nEmpty
++;
        sem_post(
&lock);
        sem_wait(
&emptyCond);
        sem_wait(
&lock);
        nEmpty
--;
    }

    DeQueue(msg);
    
if(nFull>0)
    
{
        sem_post(
&fullCond);
    }

    sem_post(
&lock);
}

void destroyThreadQueue()
{
    destroyCircleQueue(queue);
    sem_destroy(
&lock);
    sem_destroy(
&fullCond);
    sem_destroy(
&emptyCond);
}

posted on 2008-01-15 18:16 活着就是折腾,所以当然要骠悍的折腾 阅读(402) 评论(0)  编辑 收藏 引用 所属分类: 多线程

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理