• 阻塞队列实现


    0 前言

          阻塞队列在生产业务的很多场景里,都有使用的需要。例如:在数据流式处理服务中,我们需要异步的执行上游逻辑a与下游逻辑b;在rpc网络通讯框架场景中,我们需要解耦网络读写线程与消息处理线程。总之, 阻塞队列是在不同职责的线程之间进行数据沟通的桥梁。在jdk里面有现成的BlockingQueue类,现在让我们看看一个C++版的实现吧: 

    1 实现源码

       1.1 锁封装

        通过信号量保证不同线程之间数据操作的一致性。

    class CSemaphore
    
    {
    
     public:
    
      CSemaphore()
    
      {
    
        sem_init(&m_sem, 0, 0);
    
      }
    
     
    
      ~CSemaphore()
    
      {
    
        sem_destroy(&m_sem);
    
      }
    
     
    
      void Produce()
    
      {
    
        sem_post(&m_sem);
    
      }
    
     
    
      void Consume()
    
      {
    
        while (sem_wait(&m_sem) != 0)
    
        {
    
          sched_yield();
    
        }
    
      }
    
     
    
      bool Try()
    
      {
    
        int value = 0;
    
        int ret = sem_getvalue(&m_sem, &value);
    
        if(ret < 0 || value <= 0)
    
        {
    
          return false;
    
        }
    
        return true;
    
      }
    
     
    
      bool TryTime(int micSec)
    
      {
    
        struct timespec ts;
    
        clock_gettime(CLOCK_REALTIME,&ts);
    
        if(micSec >= 1000000)
    
          ts.tv_sec += micSec/1000000;
    
        ts.tv_nsec += micSec%1000000*1000;
    
        if(ts.tv_nsec >= 1000000000)
    
        {
    
          ++ts.tv_sec;
    
          ts.tv_nsec -= 1000000000;
    
        }
    
     
    
        int ret = sem_timedwait(&m_sem,&ts);
    
        if(ret < 0)
    
          return false;
    
        return true;
    
      }
    
     
    
      int GetCount()
    
      {
    
        int value = 0;
    
        int ret = sem_getvalue(&m_sem, &value);
    
        if(ret < 0)
    
          return -1;
    
        else
    
          return value;
    
      }
    
     private:
    
      sem_t  m_sem;
    
    };
    View Code

       1.2 写数据(消息)   

      bool Put(const __T& value)
      {
    
        CMutexLock lock(m_mutex);
    
        if(m_queue.size() > m_queMax)
    
        { 
    
          return false;
    
        } 
    
        m_queue.push_back(value);
    
        m_semaphore.Produce();
    
        return true;
    
      }

       1.3 读取数据(消息)    

      bool Get(__T& value)
      {
    
        m_semaphore.Consume();
    
        CMutexLock lock(m_mutex);
    
        if(m_queue.empty())
    
          return false;
    
        value = m_queue.front();
    
        m_queue.pop_front();
    
        return true;
    
      }

    2 实例

    2.1 源码

    2.2 输出 

    thread id : 139737310840576 output is: 557

    thread id : 139737310840576 output is: 558

    thread id : 139737310840576 output is: 559

    thread id : 139737310840576 output is: 560

    thread id : 139737310840576 output is: 561

    thread id : 139737310840576 output is: 562

    thread id : 139737310840576 output is: 563

    thread id : 139737310840576 output is: 564

    thread id : 139737310840576 output is: 565

    thread id : 139737300350720 output is: 566

    thread id : 139737300350720 output is: 567

    thread id : 139737300350720 output is: 568

    thread id : 139737300350720 output is: 569

    thread id : 139737300350720 output is: 570

    thread id : 139737310840576 output is: 571

      源码请见附件 http://files.cnblogs.com/files/gisorange/blockqueue.zip

  • 相关阅读:
    validate BST
    LC282. Expression Add Operators
    nginx统计日志命令
    iptables和firewalld命令
    nginx安装
    测试服务器IO
    规范主机名和设置最大文件进程数
    Docker安装
    MySQL/MariaDB二进制安装
    Docker原理
  • 原文地址:https://www.cnblogs.com/gisorange/p/4891104.html
Copyright © 2020-2023  润新知