又有了新思路,复用线程
ThreadPool.hpp
# pragma once
# include <thread>
# include <memory>
# include <functional>
# include <utility>
# include <condition_variable>
# include <atomic>
# include <queue>
# include <vector>
# include <future>
class ThreadAdapter {
protected :
bool stop = false ;
std:: shared_ptr< std:: thread> m_t;
std:: mutex m_mutex;
public :
enum class ThreadStatus {
WAIT,
RUNNING,
} ;
std:: atomic< ThreadStatus> status = ThreadStatus:: WAIT;
explicit ThreadAdapter ( std:: queue< std:: function< void ( ) >> & fq, std:: condition_variable & cv, std:: mutex & fqM) {
m_t = std:: make_shared< std:: thread> ( [ this , & q = fq, & c = cv, & m = fqM] ( ) {
while ( ! stop) {
std:: function< void ( ) > fun;
while ( true ) {
{
std:: unique_lock< std:: mutex> l ( m) ;
if ( ! q. empty ( ) ) {
fun = q. front ( ) ;
q. pop ( ) ;
break ;
}
}
std:: unique_lock< std:: mutex> lock ( m_mutex) ;
c. wait ( lock) ;
}
this -> status = ThreadStatus:: RUNNING;
if ( fun) {
fun ( ) ;
}
this -> status = ThreadStatus:: WAIT;
c. notify_all ( ) ;
}
} ) ;
}
void Detach ( ) {
if ( this -> status != ThreadStatus:: WAIT && m_t-> joinable ( ) ) {
this -> stop = true ;
m_t-> detach ( ) ;
}
}
~ ThreadAdapter ( ) {
if ( this -> status != ThreadStatus:: WAIT && m_t-> joinable ( ) ) {
this -> stop = true ;
m_t-> join ( ) ;
}
}
} ;
class ThreadPool {
protected :
std:: queue< std:: function< void ( ) >> fq;
std:: mutex fqM;
std:: condition_variable cv;
std:: vector< std:: shared_ptr< ThreadAdapter>> t;
public :
explicit ThreadPool ( int s) {
for ( int i = 0 ; i < s; ++ i) {
auto p = std:: make_shared< ThreadAdapter> ( fq, cv, fqM) ;
t. emplace_back ( std:: move ( p) ) ;
}
}
template < typename F , typename . . . Args>
decltype ( auto ) AddTask ( F && func, Args && . . . args) {
using res_type = typename std :: result_of< F ( Args. . . ) > :: type;
auto task = std:: make_shared< std:: packaged_task< res_type ( ) >> (
std:: bind ( std:: forward< F> ( func) , std:: forward< Args> ( args) . . . ) ) ;
std:: future< res_type> res = task-> get_future ( ) ;
{
{
std:: unique_lock< std:: mutex> lock ( fqM) ;
fq. emplace ( [ task] ( ) { ( * task) ( ) ; } ) ;
}
cv. notify_one ( ) ;
}
return res;
}
} ;
test.cpp
# include <iostream>
# include <thread>
# include "ThreadPool.hpp"
# include <atomic>
using namespace std;
int main ( ) {
ThreadPool threadPool ( 10 ) ;
mutex m;
std:: atomic< int > at = 0 ;
for ( int i = 0 ; i < 100000 ; ++ i) {
threadPool. AddTask ( [ & a = at] ( ) {
for ( int j = 0 ; j < 1000 ; ++ j) {
a++ ;
}
} ) ;
}
for ( int i = 0 ; i < 100 ; ++ i) {
cout << at << endl;
std:: this_thread:: sleep_for ( std:: chrono:: milliseconds ( 1 ) ) ;
}
std:: this_thread:: sleep_for ( std:: chrono:: minutes ( 100 ) ) ;
return 0 ;
}