@@ -267,34 +267,112 @@ threadPool->start([=]{
267
267
268
268
```cpp
269
269
class ThreadPool {
270
- std::mutex mutex ;
271
- std::condition_variable cv ;
272
- std::atomic<bool> stop ;
273
- std::atomic<std::size_t> thread_num ;
274
- std::queue<Task> tasks ;
275
- std::vector<std::thread> pool ;
270
+ std::mutex mutex_ ;
271
+ std::condition_variable cv_ ;
272
+ std::atomic<bool> stop_ ;
273
+ std::atomic<std::size_t> num_threads_ ;
274
+ std::queue<Task> tasks_ ;
275
+ std::vector<std::thread> pool_ ;
276
276
};
277
277
```
278
278
279
- 1 . ** ` std::mutex mutex ` **
280
-
279
+ 1 . ** ` std::mutex mutex_ ` **
281
280
- 用于保护共享资源(如任务队列)在多线程环境中的访问,避免数据竞争。
282
281
283
- 2 . ** ` std::condition_variable cv ` **
284
-
282
+ 2 . ** ` std::condition_variable cv_ ` **
285
283
- 用于线程间的同步,允许线程等待特定条件(如新任务加入队列)并在条件满足时唤醒线程。
286
284
287
- 3 . ** ` std::atomic<bool> stop ` **
285
+ 3 . ** ` std::atomic<bool> stop_ ` **
288
286
- 用于指示线程池是否停止接收新任务,并安全地通知所有工作线程退出。
289
287
290
- 4 . ** ` std::atomic<std::size_t> thread_num ` **
291
-
288
+ 4 . ** ` std::atomic<std::size_t> num_threads_ ` **
292
289
- 表示线程池中的线程数量。
293
290
294
- 5 . ** ` std::queue<Task> tasks ` **
295
-
291
+ 5 . ** ` std::queue<Task> tasks_ ` **
296
292
- 任务队列,存储等待执行的任务,任务按提交顺序执行。
297
293
298
- 6 . ** ` std::vector<std::thread> pool ` **
294
+ 6 . ** ` std::vector<std::thread> pool_ ` **
299
295
300
296
- 线程容器,存储管理线程对象,每个线程从任务队列中获取任务并执行。
297
+
298
+ 那么再直接提供构造函数以及添加任务到线程池的接口,然后内部再进行一点小小的操作,也就完成了:
299
+
300
+ ``` cpp
301
+ inline std::size_t default_thread_pool_size ()noexcept {
302
+ std::size_t num_threads = std::thread::hardware_concurrency() * 2;
303
+ num_threads = num_threads == 0 ? 2 : num_threads;
304
+ return num_threads;
305
+ }
306
+
307
+ class ThreadPool {
308
+ public:
309
+ using Task = std::packaged_task<void()>;
310
+
311
+ ThreadPool(const ThreadPool&) = delete;
312
+ ThreadPool& operator=(const ThreadPool&) = delete;
313
+
314
+ ThreadPool(std::size_t num_thread = default_thread_pool_size())
315
+ : stop_{ false }, num_threads_{ num_thread } {
316
+ start();
317
+ }
318
+ ~ThreadPool (){
319
+ stop ();
320
+ }
321
+
322
+ template<typename F, typename... Args>
323
+ std::future<std::invoke_result_t<std::decay_t<F>, std::decay_t<Args>...>> submit(F&& f, Args&&...args){
324
+ using RetType = std::invoke_result_t<std::decay_t<F>, std::decay_t<Args>...>;
325
+ if (stop_.load()){
326
+ throw std::runtime_error("ThreadPool is stopped");
327
+ }
328
+
329
+ auto task = std::make_shared<std::packaged_task<RetType()>>(
330
+ std::bind (std::forward<F >(f), std::forward<Args >(args)...));
331
+ std::future<RetType > ret = task->get_future();
332
+
333
+ {
334
+ std::lock_guard<std::mutex> lc{ mutex_ };
335
+ tasks_.emplace([task] {(*task)(); });
336
+ }
337
+ cv_.notify_one();
338
+ return ret;
339
+ }
340
+
341
+ void stop(){
342
+ stop_.store(true);
343
+ cv_.notify_all();
344
+ for (auto& thread : pool_){
345
+ if (thread.joinable()) {
346
+ thread.join();
347
+ }
348
+ }
349
+ }
350
+
351
+ void start(){
352
+ for (std::size_t i = 0; i < num_threads_; ++i){
353
+ pool_.emplace_back([this] {
354
+ while (!stop_) {
355
+ Task task;
356
+ {
357
+ std::unique_lock<std::mutex> lc{ mutex_ };
358
+ cv_.wait(lc, [this] {return stop_ || !tasks_.empty(); });
359
+ if (tasks_.empty())
360
+ return;
361
+ task = std::move(tasks_.front());
362
+ tasks_.pop();
363
+ }
364
+ task ();
365
+ }
366
+ });
367
+ }
368
+ }
369
+
370
+ private:
371
+ std::mutex mutex_ ;
372
+ std::condition_variable cv_ ;
373
+ std::atomic<bool > stop_ ;
374
+ std::atomic< std::size_t > num_threads_ ;
375
+ std::queue<Task > tasks_ ;
376
+ std::vector< std::thread > pool_ ;
377
+ };
378
+ ```
0 commit comments