最近打算做一个服务器端程序,每来一个客户端请求新开一个线程进行处理。在网上查了一些资料后,准备使用线程池来做这个东西。使用C++11新的库处理想线程问题比以前简单了许多,在网上找到一份线程池的实现,http://blog.csdn.net/goldenhawking/article/details/7919547    这个线程池实现中,每一个线程都维护一个任务队列,我觉得这么做不利于任务调度,有可能某个线程的待执行任务列表很长,而其他线程则在休眠。

下面是我自己实现的一个线程池,任务队列由线程池类来分配,每个线程只有拿到任务的时候才执行,其他时间是阻塞的。另外,如果没有任务需要执行,那么分配任务的线程也会阻塞,直到来了新任务。 代码在VS2013下测试通过。

本人菜鸟一枚,欢迎指出错误。

threadInstance.h

 #pragma once

 #include <iostream>
#include <thread>
#include <mutex>
#include <functional>
#include <list>
#include <atomic>
#include <vector>
#include <algorithm>
#include <memory>
#include <condition_variable> class ThreadPool; //thread class
class ThreadInstance
{
public:
ThreadInstance(ThreadPool *theadPool)
:m_stop(false), m_pthread(nullptr), m_threadPool(theadPool)
{ }
virtual ~ThreadInstance()
{
if (m_pthread != nullptr)
{
m_pthread->join();
delete m_pthread;
} } void begin()
{
m_pthread = new std::thread(std::bind(&ThreadInstance::run, this));
}
void run();
void join()
{
m_stop = true;
std::lock_guard<std::mutex> lg(m_mutex_task);
m_task = nullptr;
m_cond_task_ready.notify_one();
} void set_task(std::function<void(void)> &task)
{
std::lock_guard<std::mutex> lg(m_mutex_task);
m_task = task;
} public:
//condition_variable to wait for task
std::condition_variable m_cond_task_ready;
protected:
//flag used to terminate the thread
std::atomic< bool> m_stop;
//mutex used by member m_cond_task_ready
std::mutex m_mutex_cond;
//int m_id; //task to be executed
std::function<void(void)> m_task;
// mutex to protect m_task
std::mutex m_mutex_task;
//pointer to thread
std::thread *m_pthread;
// pointer to thread pool
ThreadPool *m_threadPool;
};

threadInstance.cpp

 #include "threadInstance.h"
#include "threadPool.h" void ThreadInstance::run()
{ while (true)
{
//auto x = std::this_thread::get_id();
std::unique_lock<std::mutex> lck(m_mutex_cond);
m_cond_task_ready.wait(lck); if (m_stop)
{
break;
}
m_task(); //shared_ptr<ThreadInstance> ptr(this);
m_threadPool->append_free_thread(this);
} }

threadPool.h

 #pragma once

 #include <thread>
#include <mutex>
#include <functional>
#include <list>
#include <atomic>
#include <vector>
#include <algorithm>
#include <memory>
#include <condition_variable> //semaphore class used to represent free threads and task
class Semaphore {
public:
Semaphore(int value = ) : count(value)
{} void wait(){
std::unique_lock<std::mutex> lock(m_mutex);
if (--count < ) // count is not enough ?
condition.wait(lock); // suspend and wait...
}
void signal(){
std::lock_guard<std::mutex> lock(m_mutex);
//if (++count <= 0) // have some thread suspended ?
count++;
condition.notify_one(); // notify one !
} private:
int count;
std::mutex m_mutex;
std::condition_variable condition;
}; class ThreadInstance; //the thread pool class
class ThreadPool
{
public:
ThreadPool(int nThreads);
~ThreadPool();
public:
//total threads;
size_t count(){ return m_vec_threads.size(); } //wait until all threads is terminated;
void join_all(); //append task to the thread pool
void append(std::function< void(void) > func);
//start service
void start();
//append free thread to free thread list
void append_free_thread(ThreadInstance* pfThread); protected:
//function to be execute in a separate thread
void start_thread(); public:
//NO. threads
int m_n_threads;
//flag used to stop the thread pool service
std::atomic<bool> m_stop; Semaphore m_sem_free_threads;
Semaphore m_sem_task; //list contains all the free threads
std::list<ThreadInstance*> m_list_free_threads;
//vector contains all the threads
std::vector<ThreadInstance* > m_vec_threads; //std::mutex m_mutex_list_task;
std::list<std::function<void(void)>> m_list_tasks;
};

threadPool.cpp

#include "threadPool.h"
#include "threadInstance.h" std::mutex cond_mutex;
std::condition_variable cond_incoming_task; ThreadPool::ThreadPool(int nThreads)
:m_n_threads(nThreads), m_sem_free_threads(nThreads), m_sem_task(), m_stop(false)
{
for (int i = ; i < nThreads; i++)
{
ThreadInstance* ptr=new ThreadInstance(this);
m_vec_threads.push_back(ptr);
m_list_free_threads.push_back(ptr);
} } ThreadPool::~ThreadPool()
{
for (int i = ; i != m_n_threads; ++i)
{
//m_vec_threads[i]->join();
delete m_vec_threads[i];
}
} void ThreadPool::start()
{
//to avoid blocking the main thread
std::thread t(std::bind(&ThreadPool::start_thread, this));
t.detach();
}
void ThreadPool::start_thread()
{
for (auto free_thread:m_list_free_threads)
{
free_thread->begin();
} while (true)
{
//whether there's free thread and existing task
m_sem_free_threads.wait();
m_sem_task.wait(); if (m_stop)
{
break;
} // take a free thread
ThreadInstance* ptr = m_list_free_threads.front();
m_list_free_threads.pop_front(); ptr->set_task(m_list_tasks.front());
m_list_tasks.pop_front(); // awaken a suspended thread
ptr->m_cond_task_ready.notify_one();
}
}
void ThreadPool::append(std::function< void(void) > func)
{
//std::lock_guard<std::mutex> lg(m_mutex_list_task);
m_list_tasks.push_back(func);
m_sem_task.signal();
} void ThreadPool::append_free_thread(ThreadInstance* pfThread)
{
//this function only push back thread in free thread list
// it does not need to lock the list //m_mutex_free_thread.lock();
m_list_free_threads.push_back(pfThread);
//m_mutex_free_thread.unlock();
m_sem_free_threads.signal(); } void ThreadPool::join_all()
{
std::for_each(m_vec_threads.begin(), m_vec_threads.end(), [this](ThreadInstance* & item)
{
item->join();
}); m_stop = true;
m_sem_free_threads.signal();
m_sem_task.signal(); }

用于测试的main函数

 #include <iostream>
#include <thread>
#include <mutex>
#include <functional>
#include <list>
#include <atomic>
#include <vector>
#include <algorithm>
#include <memory>
#include <condition_variable> #include "threadPool.h"
//#include <vld.h> using namespace std;
class A
{
public:
A()
{}
~A(){}
public:
void foo(int k)
{
//sleep for a while
std::this_thread::sleep_for(std::chrono::milliseconds(rand() % + ));
std::cout << "k = " << k << std::endl; }
}; //a function which will be executed in sub thread.
void hello()
{
//sleep for a while
std::this_thread::sleep_for(std::chrono::milliseconds());
cout << "hello \n";
} //let's test the thread.
int main()
{
srand(); ThreadPool g_threadPool();
A a; g_threadPool.append(&hello); //append object method with copy-constructor(value-assignment)
g_threadPool.append(std::bind(&A::foo, a, ));
g_threadPool.append(std::bind(&A::foo, a, ));
g_threadPool.append(std::bind(&A::foo, a, ));
g_threadPool.append(std::bind(&A::foo, a, )); //auto beg = std::chrono::high_resolution_clock().now(); g_threadPool.start(); //std::this_thread::sleep_for(std::chrono::milliseconds(5000)); g_threadPool.append(&hello);
//append object method with address assignment, will cause the objects' member increase.
g_threadPool.append(std::bind(&A::foo, &a, ));
g_threadPool.append(std::bind(&A::foo, &a, ));
g_threadPool.append(std::bind(&A::foo, &a, ));
g_threadPool.append(std::bind(&A::foo, &a, )); //std::this_thread::sleep_for(std::chrono::seconds(5));
char temp;
cin >> temp;
if (temp == 'e')
{
g_threadPool.join_all();
} //auto end = std::chrono::high_resolution_clock().now();
//auto dd = std::chrono::duration_cast<chrono::seconds>(end - beg);
//cout << dd.count() << endl; return ;
}

使用C++11 实现的线程池的更多相关文章

  1. C++11的简单线程池代码阅读

    这是一个简单的C++11实现的线程池,代码很简单. 原理就是管理一个任务队列和一个工作线程队列. 工作线程不断的从任务队列取任务,然后执行.如果没有任务就等待新任务的到来.添加新任务的时候先添加到任务 ...

  2. 第11章 Windows线程池(3)_私有的线程池

    11.3 私有的线程池 11.3.1 创建和销毁私有的线程池 (1)进程默认线程池 当调用CreateThreadpoolwork.CreateThreadpoolTimer.CreateThread ...

  3. 第11章 Windows线程池(1)_传统的Windows线程池

    第11章 Windows线程池 11.1 传统的Windows线程池及API (1)线程池中的几种底层线程 ①可变数量的长任务线程:WT_EXECUTELONGFUNCTION ②Timer线程:调用 ...

  4. 基于无锁队列和c++11的高性能线程池

    基于无锁队列和c++11的高性能线程池线程使用c++11库和线程池之间的消息通讯使用一个简单的无锁消息队列适用于linux平台,gcc 4.6以上   标签: <无>   代码片段(6)[ ...

  5. Windows核心编程:第11章 Windows线程池

    Github https://github.com/gongluck/Windows-Core-Program.git //第11章 Windows线程池.cpp: 定义应用程序的入口点. // #i ...

  6. [C++]C风格、C++风格和C++11特性的线程池

    线程池概念 假设完成一项任务需要的时间=创建线程时间T1+线程执行任务时间T2+销毁线程时间T3,如果T1+T3的时间远大于T2,通常就可以考虑采取线程池来提高服务器的性能 thread pool就是 ...

  7. 第11章 Windows线程池(2)_Win2008及以上的新线程池

    11.2 Win2008以上的新线程池 (1)传统线程池的优缺点: ①传统Windows线程池调用简单,使用方便(有时只需调用一个API即可) ②这种简单也带来负面问题,如接口过于简单,无法更多去控制 ...

  8. C++11下的线程池以及灵活的functional + bind + lamda

    利用boost的thread实现一个线程类,维护一个任务队列,以便可以承载非常灵活的调用.这个线程类可以方便的为后面的线程池打好基础.线程池还是动态均衡,没有什么别的.由于minGW 4.7 对 C+ ...

  9. Java并发(11)- 有关线程池的10个问题

    引言 在日常开发中,线程池是使用非常频繁的一种技术,无论是服务端多线程接收用户请求,还是客户端多线程处理数据,都会用到线程池技术,那么全面的了解线程池的使用.背后的实现原理以及合理的优化线程池的大小等 ...

随机推荐

  1. 【HDOJ】2289 Cup

    二分.另外,圆台体积为v = PI*(r*r+r*R+R*R)*H/3.注意精度. #include <cstdio> #include <cmath> #define exp ...

  2. (转载)mysql查询一天,查询一周,查询一个月的数据

    (转载)http://www.cnblogs.com/likwo/archive/2010/04/16/1713282.html 查询一天: select * from table where to_ ...

  3. 字符串(后缀自动机):NOI 2016 优秀的拆分

    [问题描述] 如果一个字符串可以被拆分为 AABB 的形式,其中 A 和 B 是任意非空字符串, 则我们称该字符串的这种拆分是优秀的. 例如,对于字符串 aabaabaa,如果令 A = aab, B ...

  4. 动态规划(背包问题):HRBUST 1377 金明的预算方案

    金明的预算方案 金明今天很开心,家里购置的新房就要领钥匙了,新房里有一间金明自己专用的很宽敞的房间.更让他高兴的是,妈妈昨天对他说:“你的房间需要购买哪些物品,怎么布置,你说了算,只要不超过N元钱就行 ...

  5. Oracle用户管理

    创建用户 概述:在oracle中要创建一个新的用户使用create user 语句,一般是具有dba(数据库管理员)的权限才能使用. create user 用户名 identified by 密码: ...

  6. HDOJ(HDU) 2148 Score(比较、)

    Problem Description 转眼又到了一年的年末,Lele又一次迎来了期末考试.虽然说每年都要考试,不过今年的这场考试对Lele来说却意义重大. 因为经济原因,如果今年没有排在班级前几名, ...

  7. TXT四则运算计算器

    基本思想:使用getline函数从TXT文件中依次读出中缀表达式,将其转为后缀表达式后计算结果,并与用户结果比对. 整数.分数.小数的处理:将小数和整数都视为默认分母为1的分数.建立分数类,在中缀转换 ...

  8. 遍历Map的几种方法

    public static void main(String[] args) { Map<String, String> map = new HashMap<String, Stri ...

  9. Struts2 入门(新手必看)

    船舶停靠在港湾是很安全的,但这不是造船的目的     Struts 2及其优势 Struts 2是一个MVC框架,以WebWork框架的设计思想为核心,吸收了Struts 1的部分优点 Struts ...

  10. 怎样在loop中处理异常

    怎样在loop中处理异常,而不跳出 出现符号“exception”在需要下下列之一时的解决办法; 如果sql中发生异常,我们可以用 exception       when others then d ...