多线程的N种模式

  1. 多线程有两种基本模式

    1. 线程池模式
    2. 生产者/消费者模式

总结

  1. 方案1 适合有少量多线程处理
  2. 方案2 适合常驻的对延时要求不高的多线程
  3. 方案3 适合有大量任务不停的产生,并且对延时敏感的多线程

情景模拟

  1. 我们有1W个任务要处理
  2. 我们的运行环境 最多支持并行100个任务

线程池模式

  1. 我们新建一个 线程池,设置他只允许 并行100个任务
  2. 我们读取任务列表 依次创建1W个线程,并且放入线程池运行

生产者/消费者模式

  1. 我们 先设计一个任务队列,可以存取任务
  2. 任务的 增加/取出 等操作 一定要 互斥
  3. 我们创建100个线程
  4. 每个线程都反复取出 任务队列里的任务,并且处理
  5. 直至所有任务都处理后退出

多线程设计模型

方案1 即时创建

  1. 线程运行后,自己结束
  2. 没有任务时不创建线程
  3. 有任务时创建线程池

优点:

  1. 任务较少时节省资源

缺点:

  1. 任务较多时,线程池中会有大量线程被创建后等待
  2. 大量闲置线程会占据很多内存

方案2 线程永生

  1. 线程的数量是恒定的
  2. 没有任务时 线程自己定时检查是否有任务
  3. 有任务时 取出并处理任务

优点:

  1. 即使任务数量很大也不会有大量线程被创建后等待

缺点:

  1. 即使任务很少 也会占用一部分资源
  2. 检查任务/等待任务 本就会造成一些延时

方案3 即时唤醒_永生线程(推荐)

  1. 子线程的数量是恒定的
  2. 子线程 没有任务时 等待唤醒 WaitForSingleObject
  3. 我们在主线程中判断有多少任务,并且决定 唤醒几个线程ReleaseSemaphore

    1. 所有子线程会循环处理所有任务
    2. 子线程发现没有任务时不要 ReleaseSemaphore,直接进入休眠状态WaitForSingleObject
  4. 重复步骤三

优点:

  1. 解决了 线程永生 导致的 任务处理延时
  2. 解决了 即时创建 导致的 大量子线程闲置/等待
  3. 可以动态决定 任务并行数量

缺点:

  1. 代码移植性较差
  2. 非常依赖 底层的唤醒机制
  3. 在某些情况下 不如线程永生

伪代码

//定义子线程

 DWORD my_thread()
 {
    while(等待被唤醒)
    {
      while(1)
      {
        //=============线程互斥代码块
        
        if(有任务){
        取任务;
        任务列表删除 我们选择的任务;
        }else{
        n_count 原子+1;
        break; //我们回到最外层 while
        }
        
        //=============线程互斥代码块
        
        //处理我们拿到的任务
        
      }
    }
 }

 //定义 主线程
 
 1 分析任务状态
 2 根据需要 唤醒线程
 3 等待 线程全部结束
 4 结束运行/回到第一步
Last modification:October 26, 2018
如果觉得我的文章对你有用,请随意赞赏