【c++11 新特性应用】利用bind实现通用的混合任务线程池
2017-07-05 22:51
459 查看
先简单认识一下std::bind,详细资料查阅相关资料,这里不啰嗦,假设你已经具备了理论知识:
auto f1 = bind(&fun_int, 3,std::placeholders::_1);
这名话的意思是给fun_int绑定2个参数,第一个是3,第二个本来的第1个参数,返回一个函数对象,这样调用f1(5) 等价于调用fun_int(3,5)
这样,bind就可以将任意函数的任意具体调用,生成一个指定的调用方式,比如无参调用,这样线程池只需要维护类型是std::function<void()>类型的对象即可。
具体实现如下,3个文件,ThreadPool.cpp ThreadPool.h,main.cpp是测试文件。condition_variable之前没有用过,用的都是linux c标准的,这里现学现用,可能用bug,复核后再参考。
ThreadPool.h
ThreadPool.cpp
#include <iostream>
#include "ThreadPool.h"
ThreadPool::ThreadPool(int tnum)
{
//初始化放在线程初始化之前
for(int i = 0; i < tnum; i++)
m_threads.push_back(thread(&ThreadPool::Run, this, i));
}
ThreadPool::~ThreadPool()
{
Stop();
}
void ThreadPool::Run(int id)
{
while(true)
{
unique_lock<mutex> lck(m_mtx);
while(m_tasks.empty())
{
if(!m_running)
{
cout << "----thread end " << id << endl;
return;
}
m_cv.wait(lck);
}
//
cout << "----deal task " << id << endl;
auto t = m_tasks.front();
m_tasks.pop();
t();
}
}
void ThreadPool::Stop()
{
cout << "----Stop" << endl;
m_running = false;
while(!m_tasks.empty()) //消化完队列再终止
{
unique_lock<mutex> lck(m_mtx);
m_cv.notify_all();
}
m_mtx.lock(); //这里不可以使用unique_lock<mutex>,释放时机晚于join,形成死锁
m_cv.notify_all();
m_mtx.unlock();
for(auto& item : m_threads)
item.join();
m_threads.clear();
}
bool ThreadPool::AddTask(TaskType task)
{
cout << "----push taks" << endl;
unique_lock<mutex> lck(m_mtx);
m_tasks.push(task);
m_cv.notify_one();
return true;
}
main.cpp
#include <string>
#include <iostream>
#include "ThreadPool.h"
using namespace std;
class Obj
{
int m_val;
public:
Obj(int val) : m_val(val) {}
void DisPlay()
{
cout << "DisPlay: " << m_val << endl;
}
};
void fun_int(int a)
{
cout << "fun int " << a << endl;
}
void fun_string(string a, int max)
{
cout << "fun string " << a.length() << " " << max << endl;
}
int main()
{
auto f1 = bind(&fun_int, 3);
auto f2 = bind(&fun_int, 5);
auto f3 = bind(&fun_string, "test", 1);
auto f4 = bind(&Obj::DisPlay, Obj(11));
function<void()> f5 = bind(&Obj::DisPlay, Obj(22));
//
ThreadPool pool(3);
pool.AddTask(f1);
pool.AddTask(f2);
pool.AddTask(f3);
pool.AddTask(f4);
pool.AddTask(f5);
return 0;
}
auto f1 = bind(&fun_int, 3,std::placeholders::_1);
这名话的意思是给fun_int绑定2个参数,第一个是3,第二个本来的第1个参数,返回一个函数对象,这样调用f1(5) 等价于调用fun_int(3,5)
这样,bind就可以将任意函数的任意具体调用,生成一个指定的调用方式,比如无参调用,这样线程池只需要维护类型是std::function<void()>类型的对象即可。
具体实现如下,3个文件,ThreadPool.cpp ThreadPool.h,main.cpp是测试文件。condition_variable之前没有用过,用的都是linux c标准的,这里现学现用,可能用bug,复核后再参考。
ThreadPool.h
#pragma once #include <functional> #include <vector> #include <thread> #include <queue> #include <mutex> #include <condition_variable> using namespace std; typedef function<void()> TaskType; class ThreadPool { mutex m_mtx; condition_variable m_cv; bool m_running = true; vector<thread> m_threads; // queue<TaskType> m_tasks; void Run(int id); public: //初始化,自动启用线程 ThreadPool(int tnum); //析构,终止 ~ThreadPool(); //添加一个任务 bool AddTask(TaskType task); //终止线程池,消化完所有任务 void Stop(); };
ThreadPool.cpp
#include <iostream>
#include "ThreadPool.h"
ThreadPool::ThreadPool(int tnum)
{
//初始化放在线程初始化之前
for(int i = 0; i < tnum; i++)
m_threads.push_back(thread(&ThreadPool::Run, this, i));
}
ThreadPool::~ThreadPool()
{
Stop();
}
void ThreadPool::Run(int id)
{
while(true)
{
unique_lock<mutex> lck(m_mtx);
while(m_tasks.empty())
{
if(!m_running)
{
cout << "----thread end " << id << endl;
return;
}
m_cv.wait(lck);
}
//
cout << "----deal task " << id << endl;
auto t = m_tasks.front();
m_tasks.pop();
t();
}
}
void ThreadPool::Stop()
{
cout << "----Stop" << endl;
m_running = false;
while(!m_tasks.empty()) //消化完队列再终止
{
unique_lock<mutex> lck(m_mtx);
m_cv.notify_all();
}
m_mtx.lock(); //这里不可以使用unique_lock<mutex>,释放时机晚于join,形成死锁
m_cv.notify_all();
m_mtx.unlock();
for(auto& item : m_threads)
item.join();
m_threads.clear();
}
bool ThreadPool::AddTask(TaskType task)
{
cout << "----push taks" << endl;
unique_lock<mutex> lck(m_mtx);
m_tasks.push(task);
m_cv.notify_one();
return true;
}
main.cpp
#include <string>
#include <iostream>
#include "ThreadPool.h"
using namespace std;
class Obj
{
int m_val;
public:
Obj(int val) : m_val(val) {}
void DisPlay()
{
cout << "DisPlay: " << m_val << endl;
}
};
void fun_int(int a)
{
cout << "fun int " << a << endl;
}
void fun_string(string a, int max)
{
cout << "fun string " << a.length() << " " << max << endl;
}
int main()
{
auto f1 = bind(&fun_int, 3);
auto f2 = bind(&fun_int, 5);
auto f3 = bind(&fun_string, "test", 1);
auto f4 = bind(&Obj::DisPlay, Obj(11));
function<void()> f5 = bind(&Obj::DisPlay, Obj(22));
//
ThreadPool pool(3);
pool.AddTask(f1);
pool.AddTask(f2);
pool.AddTask(f3);
pool.AddTask(f4);
pool.AddTask(f5);
return 0;
}
相关文章推荐
- C++11新特性应用--实现延时求值(std::function和std::bind)
- 利用C++11的function和bind功能,实现QStandardItemModel的通用遍历函数
- C++11新特性应用--实现延时求值(std::function和std::bind)
- C++11新特性应用--实现延时求值(std::function和std::bind)
- C++11:借助C++11特性简单高效实现线程池
- android利用线程池高效实现异步任务
- 用c++11的bind,function,boost::condition_variable实现的一个线程安全的任务队列
- 如何利用c++11的新特性编写类成员线程函数并实现同步
- 利用C++11的function和bind功能,实现QStandardItemModel的通用遍历函数
- C++11新特性应用--占位符(std::placeholders std::is_placeholder std::is_bind_expression)
- 一种利用线程池线程执行任务, 并能够结束超时任务的方法 (.NET实现)
- c++11学习笔记3——通过更通用的方法实现新特性
- ThreadPoolExecutor的应用和实现分析(中)—— 任务处理相关源码分析 线程利用(转)
- OpenGL高级特性之利用Image内存模型&计算着色器&原子操作实现(直方图模型)通用计算
- 使用c++11新特性实现线程池
- C++11新特性应用--占位符(std::placeholders std::is_placeholder std::is_bind_expression)
- android利用线程池高效实现异步任务
- C++11新特性应用--占位符(std::placeholders std::is_placeholder std::is_bind_expression)
- 本文是笔者根据数据库编程经验,利用C++语言的模板、继承、授权、多态等面向对象特性,借鉴命令模式,实现了对象在关系数据中的存储,降低应用系统与数据库之间的耦合,提高开发效率。
- C++11新特性应用--占位符(std::placeholders std::is_placeholder std::is_bind_expression)