最近打算做一个服务器端程序,每来一个客户端请求新开一个线程进行处理。在网上查了一些资料后,准备使用线程池来做这个东西。使用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. myisam和innodb索引实现的不同

    1.MyISAM 使用B+Tree 作为索引结构,叶子节点的data存放指针,也就是记录的地址.对于主键索引和辅助索引都是一样的.2.InnoDB 也使用B+Tree作为索引结构,也别需要注意的是,对 ...

  2. IntegerCache详解

    IntegerCache是Integer的内部类,用来将-128——high之间的对象进行实例化 private static class IntegerCache {        static f ...

  3. LVS+Keepalived+Nginx+Tomcat高可用负载均衡集群配置(DR模式,一个VIP,多个端口)

    一.概述 LVS作用:实现负载均衡 Keepalived作用:监控集群系统中各个服务节点的状态,HA cluster. 配置LVS有两种方式: 1. 通过ipvsadm命令行方式配置 2. 通过Red ...

  4. 【转】推荐--《Android深入浅出》----不错

    原文网址:http://www.cnblogs.com/plokmju/p/Android_Book.html 承香墨影   推荐--<Android深入浅出> 基本信息 书名:Andro ...

  5. 使用yum快速升级CentOS 6.5内核到 3.10.28

    网上有不少升级CentOS内核的文章,如<CentOS 6.5 升级内核到 3.10.28>,大部分都是下载源码编译,有点麻烦. 在yum的ELRepo源中,有mainline(3.13. ...

  6. Unique Binary Search Trees——LeetCode

    Given n, how many structurally unique BST's (binary search trees) that store values 1...n? For examp ...

  7. 科研论文提交流程与常见问题(EDAS 系统提交)

    第一步 注册文章(Registering your Paper) 如上图,点击菜单中的submit paper按钮,会列出所有的会议和期刊,选择一个你要投稿的期刊或者会议,例如选择第一个2013 IE ...

  8. 老罗android开发视频教程学习完了

    让我学到了android的文件结构,事件窗口数据传递,百度地图开发很感谢

  9. java 中的反射

    反射技术并不陌生,如何使用 ? 获取到类的全名 即可获取类中所有的信息: 构造.方法.成员变量等: 反射技术好多框架在使用,比如以前我们用jdbc,Class.forName("com.my ...

  10. Linq to sql并发与事务

    本文转载:http://www.cnblogs.com/lovecherry/archive/2007/08/20/862365.html 检测并发 首先使用下面的SQL语句查询数据库的产品表: se ...