使用C++11 实现的线程池
最近打算做一个服务器端程序,每来一个客户端请求新开一个线程进行处理。在网上查了一些资料后,准备使用线程池来做这个东西。使用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 实现的线程池的更多相关文章
- C++11的简单线程池代码阅读
这是一个简单的C++11实现的线程池,代码很简单. 原理就是管理一个任务队列和一个工作线程队列. 工作线程不断的从任务队列取任务,然后执行.如果没有任务就等待新任务的到来.添加新任务的时候先添加到任务 ...
- 第11章 Windows线程池(3)_私有的线程池
11.3 私有的线程池 11.3.1 创建和销毁私有的线程池 (1)进程默认线程池 当调用CreateThreadpoolwork.CreateThreadpoolTimer.CreateThread ...
- 第11章 Windows线程池(1)_传统的Windows线程池
第11章 Windows线程池 11.1 传统的Windows线程池及API (1)线程池中的几种底层线程 ①可变数量的长任务线程:WT_EXECUTELONGFUNCTION ②Timer线程:调用 ...
- 基于无锁队列和c++11的高性能线程池
基于无锁队列和c++11的高性能线程池线程使用c++11库和线程池之间的消息通讯使用一个简单的无锁消息队列适用于linux平台,gcc 4.6以上 标签: <无> 代码片段(6)[ ...
- Windows核心编程:第11章 Windows线程池
Github https://github.com/gongluck/Windows-Core-Program.git //第11章 Windows线程池.cpp: 定义应用程序的入口点. // #i ...
- [C++]C风格、C++风格和C++11特性的线程池
线程池概念 假设完成一项任务需要的时间=创建线程时间T1+线程执行任务时间T2+销毁线程时间T3,如果T1+T3的时间远大于T2,通常就可以考虑采取线程池来提高服务器的性能 thread pool就是 ...
- 第11章 Windows线程池(2)_Win2008及以上的新线程池
11.2 Win2008以上的新线程池 (1)传统线程池的优缺点: ①传统Windows线程池调用简单,使用方便(有时只需调用一个API即可) ②这种简单也带来负面问题,如接口过于简单,无法更多去控制 ...
- C++11下的线程池以及灵活的functional + bind + lamda
利用boost的thread实现一个线程类,维护一个任务队列,以便可以承载非常灵活的调用.这个线程类可以方便的为后面的线程池打好基础.线程池还是动态均衡,没有什么别的.由于minGW 4.7 对 C+ ...
- Java并发(11)- 有关线程池的10个问题
引言 在日常开发中,线程池是使用非常频繁的一种技术,无论是服务端多线程接收用户请求,还是客户端多线程处理数据,都会用到线程池技术,那么全面的了解线程池的使用.背后的实现原理以及合理的优化线程池的大小等 ...
随机推荐
- Maven实战五
转载:http://www.iteye.com/topic/1123232 我们项目中用到的jar包可以通过依赖的方式引入,构建项目的时候从Maven仓库下载即可. 1. 依赖配置 依赖可以声明 ...
- [置顶] export命令-linux
export 命令 功能说明: 设置或显示环境变量. 语 法: export [-fnp][变量名称]=[变量设置值] 补充说明: 在shell中执行程序时,shell会提供一组环境变量. expor ...
- Linux中查看进程的多线程pstree, ps -L
Linux中查看进程的多线程 在SMP系统中,我们的应用程序经常使用多线程的技术,那么在Linux中如何查看某个进程的多个线程呢? 本文介绍3种命令来查看Linux系统中的线程(LWP)的情况:在我的 ...
- 数学(线性规划):UVAoj 10498 Happiness
Problem GHappiness! Input: standard inputOutput: standard outputTime Limit: 3 seconds Prof. Kaykobad ...
- SQL时间格式化
1 取值后格式化 {:d}小型:如2005 {:D}大型:如2005年5月6日 {:f}完整型 2 当前时间获取 DateTime.Now.ToShortDateString 3 取值中格式化SQL ...
- [转载][HTML] 普通的DIV分层以及版透明效果
来源忘记哪的了,我稍微做了点修改,想了想还是挂了转载的标签,嗯嗯: <html> <head> <title>EXAMPLE</title> </ ...
- cf602A Two Bases
A. Two Bases time limit per test 1 second memory limit per test 256 megabytes input standard input o ...
- Hibernate配置文件中hiberante.hbm2ddl.auto四个参数的配置
我们在搭建环境的时候,在配置文件中有一个属性标签为: <property name="hibernate.hbm2ddl.auto"> </propert ...
- poj1611 并查集
题目链接:http://poj.org/problem?id=1611 #include <cstdio> #include <cmath> #include <algo ...
- Hibernate二 映射 注解 一级缓存
Hibernate映射1.@Entity 被该注解修饰的POJO类是一个实体,可以用name属性指定该实体类的名称,系统默认以该类的类名作为实体类的名称.2.@Table 指定持久化类所映射的表,它的 ...