这个线程池代码是不是尝试双重执行任务?

Posted

技术标签:

【中文标题】这个线程池代码是不是尝试双重执行任务?【英文标题】:Is this threadpool code attempting double execution of task?这个线程池代码是否尝试双重执行任务? 【发布时间】:2021-10-04 19:27:00 【问题描述】:

我从https://pastebin.com/MM5kSvH6 复制了以下线程池实现。一切看起来都不错,但我无法理解第 32 行和第 71 行的逻辑。这两行不是都在尝试执行该功能吗?我想在线程池中,线程应该从任务队列中提取任务然后执行它?从这个意义上说,第 71 行看起来不错,但我对第 32 行感到困惑。为什么不将任务添加到队列中,为什么要尝试执行相同的操作?

#include <condition_variable>
#include <functional>
#include <iostream>
#include <future>
#include <vector>
#include <thread>
#include <queue>
 
class ThreadPool

public:
    using Task = std::function<void()>;
 
    explicit ThreadPool(std::size_t numThreads)
    
        start(numThreads);
    
 
    ~ThreadPool()
    
        stop();
    
 
    template<class T>
    auto enqueue(T task)->std::future<decltype(task())>
    
        auto wrapper = std::make_shared<std::packaged_task<decltype(task()) ()>>(std::move(task));
 
        
            std::unique_lock<std::mutex> lockmEventMutex;
            mTasks.emplace([=] 
                (*wrapper)();
            );
        
 
        mEventVar.notify_one();
        return wrapper->get_future();
    
 
private:
    std::vector<std::thread> mThreads;
 
    std::condition_variable mEventVar;
 
    std::mutex mEventMutex;
    bool mStopping = false;
 
    std::queue<Task> mTasks;
 
    void start(std::size_t numThreads)
    
        for (auto i = 0u; i < numThreads; ++i)
        
            mThreads.emplace_back([=] 
                while (true)
                
                    Task task;
 
                    
                        std::unique_lock<std::mutex> lockmEventMutex;
 
                        mEventVar.wait(lock, [=]  return mStopping || !mTasks.empty(); );
 
                        if (mStopping && mTasks.empty())
                            break;
 
                        task = std::move(mTasks.front());
                        mTasks.pop();
                    
 
                    task();
                
            );
        
    
 
    void stop() noexcept
    
        
            std::unique_lock<std::mutex> lockmEventMutex;
            mStopping = true;
        
 
        mEventVar.notify_all();
 
        for (auto &thread : mThreads)
            thread.join();
    
;
 
int main()

    
        ThreadPool pool36;
 
        for (auto i = 0; i < 36; ++i)
        
            pool.enqueue([] 
                auto f = 1000000000;
                while (f > 1)
                    f /= 1.00000001;
            );
        
    
 
    return 0;

【问题讨论】:

这两行(32 和 71)都在 lambda 中。 @tkausl - 想更详细一点吗? 将lambda放入队列,线程池调用lambda。 @tkausl - 仍然不清楚为什么代码会尝试双重执行。你的答案没有解释清楚。第 31 行看起来像调用函数 (*wrapper)(); .不是吗?第 72 行在逻辑上是正确的,因为它是从队列中实际执行的正确位置。 第 31 行 正在 调用函数。 【参考方案1】:

第 32 行添加了一个 lambda,它在调用时执行任务,而第 71 行执行 lambda。一个简单地委托给另一个。 简而言之,第 32 行只是 lambda 的一部分,它通过第 72 行的调用执行。我们没有双重执行。相反,第 72 行是执行第 32 行所属的代码的行。

【讨论】:

以上是关于这个线程池代码是不是尝试双重执行任务?的主要内容,如果未能解决你的问题,请参考以下文章

Java如何判断线程池所有任务是不是执行完毕

JUC--自定义线程池

Java如何判断线程池所有任务是不是执行完毕

线程池的实现原理

线程池任务

线程池和任务