4

我正在使用 Boost ASIO 在 C++ 中编写一个 ThreadPool 类。以下是我到目前为止编写的代码:

线程池类

    using namespace std;
    using namespace boost;

    class ThreadPoolClass {
    private:

        /* The limit to the maximum number of threads to be
         * instantiated within this pool 
         */
        int maxThreads; 
        /* Group of threads in the Pool */
        thread_group threadPool;

        asio::io_service asyncIOService;

        void _Init()
        {
            maxThreads = 0;
        }
    public:
        ThreadPoolClass();
        ThreadPoolClass(int maxNumThreads);
        ThreadPoolClass(const ThreadPoolClass& orig);
        void CreateThreadPool();
        void RunTask(JobClass * aJob);
        virtual ~ThreadPoolClass();

    };
    ThreadPoolClass::ThreadPoolClass() {
    _Init();
    }



ThreadPoolClass::ThreadPoolClass(int maxNumThreads) {
    _Init();
    maxThreads = maxNumThreads;
}

void ThreadPoolClass::CreateThreadPool() {

    asio::io_service::work work(asyncIOService);

    for (int i = 0; i < maxThreads; i++) {
        cout<<"Pushed"<<endl;
        threadPool.create_thread(bind(&asio::io_service::run, &asyncIOService));
    }
}

void ThreadPoolClass::RunTask(JobClass * aJob) {
    cout<<"RunTask"<<endl;
    asyncIOService.post(bind(&JobClass::Run,aJob));
}

ThreadPoolClass::ThreadPoolClass(const ThreadPoolClass& orig) {
}

ThreadPoolClass::~ThreadPoolClass() {
    cout<<"Kill ye all"<<endl;
    asyncIOService.stop();
    threadPool.join_all();
}

工作类

using namespace std;

class JobClass {
private:
    int a;
    int b;
    int c;

public:

    JobClass() {
        //Empty Constructor
    }

    JobClass(int val) {
        a = val;
        b = val - 1;
        c = val + 1;
    }

    void Run()
    {
        cout<<"a: "<<a<<endl;
        cout<<"b: "<<b<<endl;
        cout<<"c: "<<c<<endl;
    }

};

主要的

using namespace std;

int main(int argc, char** argv) {

    ThreadPoolClass ccThrPool(20);
    ccThrPool.CreateThreadPool();
    JobClass ccJob(10);
    cout << "Starting..." << endl;
    while(1)
    {
        ccThrPool.RunTask(&ccJob);
    }
    return 0;
}

所以,基本上我正在创建 20 个线程,但到目前为止,我只发布了一个(相同的)任务来由 ioservice 运行(只是为了在这里保持简单并找到根本原因)。以下是我在 GDB 中运行此程序时的输出:

Pushed
[New Thread 0xb7cd2b40 (LWP 15809)]
Pushed
[New Thread 0xb74d1b40 (LWP 15810)]
Pushed
[New Thread 0xb68ffb40 (LWP 15811)]
Pushed
[New Thread 0xb60feb40 (LWP 15812)]
Pushed
[New Thread 0xb56fdb40 (LWP 15813)]
Pushed
[New Thread 0xb4efcb40 (LWP 15814)]
Pushed
[New Thread 0xb44ffb40 (LWP 15815)]
Pushed
[New Thread 0xb3affb40 (LWP 15816)]
Pushed
[New Thread 0xb30ffb40 (LWP 15817)]
Pushed
[New Thread 0xb28feb40 (LWP 15818)]
Pushed
[New Thread 0xb20fdb40 (LWP 15819)]
Pushed
[New Thread 0xb18fcb40 (LWP 15820)]
Pushed
[New Thread 0xb10fbb40 (LWP 15821)]
Pushed
[New Thread 0xb08fab40 (LWP 15822)]
Pushed
[New Thread 0xb00f9b40 (LWP 15823)]
Pushed
[New Thread 0xaf8f8b40 (LWP 15824)]
Pushed
[New Thread 0xaf0f7b40 (LWP 15825)]
Pushed
[New Thread 0xae8f6b40 (LWP 15826)]
Pushed
[New Thread 0xae0f5b40 (LWP 15827)]
Pushed
[New Thread 0xad8f4b40 (LWP 15828)]
Starting...
RunTask
Kill ye all
[Thread 0xb4efcb40 (LWP 15814) exited]
[Thread 0xb30ffb40 (LWP 15817) exited]
[Thread 0xaf8f8b40 (LWP 15824) exited]
[Thread 0xae8f6b40 (LWP 15826) exited]
[Thread 0xae0f5b40 (LWP 15827) exited]
[Thread 0xaf0f7b40 (LWP 15825) exited]
[Thread 0xb56fdb40 (LWP 15813) exited]
[Thread 0xb18fcb40 (LWP 15820) exited]
[Thread 0xb10fbb40 (LWP 15821) exited]
[Thread 0xb20fdb40 (LWP 15819) exited]
[Thread 0xad8f4b40 (LWP 15828) exited]
[Thread 0xb3affb40 (LWP 15816) exited]
[Thread 0xb7cd2b40 (LWP 15809) exited]
[Thread 0xb60feb40 (LWP 15812) exited]
[Thread 0xb08fab40 (LWP 15822) exited]
[Thread 0xb68ffb40 (LWP 15811) exited]
[Thread 0xb74d1b40 (LWP 15810) exited]
[Thread 0xb28feb40 (LWP 15818) exited]
[Thread 0xb00f9b40 (LWP 15823) exited]
[Thread 0xb44ffb40 (LWP 15815) exited]
[Inferior 1 (process 15808) exited normally]

我有两个问题:

  1. 为什么我的线程正在退出,即使我在 while 循环中发布任务?
  2. 为什么 JobClass 的输出,即变量 a、b 和 c 的值没有被打印出来?
4

2 回答 2

3

我认为发生这种情况是因为您在 CreateThreadPool 方法中创建了工作对象,该方法在超出范围时会自动销毁-> 在这种情况下 io_service 没有活动的工作并且不处理您的任务。

尝试使您的 ThreadPool 类的“工作”实例变量,而不是方法中的本地变量。

class ThreadPoolClass {
private:

    thread_group threadPool;

    asio::io_service asyncIOService;

    std::auto_ptr<asio::io_service::work> work_;

public:
};



ThreadPoolClass::ThreadPoolClass(int maxNumThreads) {
    _Init();
    maxThreads = maxNumThreads;
}

void ThreadPoolClass::CreateThreadPool() {

    work_.reset(new asio::io_service::work(asyncIOService));

    for (int i = 0; i < maxThreads; i++) {
        cout<<"Pushed"<<endl;
        threadPool.create_thread(bind(&asio::io_service::run, &asyncIOService));
    }
}
于 2012-09-08T11:43:08.857 回答
1

好的,我将是第一个承认我不知道提升的人,更具体地说,从地面上的一个洞中提升::asio,但我知道很多关于线程池和工作人员的知识。

线程应该休眠,直到收到新工作的通知,但如果它们未配置为这样做,它们可能只会完成其线程 proc 并退出,这是这种情况的一个明显迹象是启动一个池,休眠在发布任何工作之前有一段合理的时间,如果池线程全部终止,则它们没有正确等待。快速阅读 boost docs 得到了这个结果,它可能与您的问题有关。

关于这一点,是否有可能从 main() 入口点对池的析构函数实际上过早地杀死了您的工作人员?我看到了 join_all,但是那个 stop() 给了我威力。如果它做到了它的名字所暗示的那样,那将解释很多。根据文档中对该 stop() 调用的描述:

为了实现关闭,应用程序需要调用 io_service 对象的 stop() 成员函数。这将导致 io_service run() 调用尽快返回,放弃未完成的操作并且不允许调度准备好的处理程序。

立即关闭和放弃提及似乎对您当前的情况非常熟悉。

同样,我不知道来自 Adam 的 boost:asio,但是如果我这样做,我会检查 boost 线程对象的启动配置。他们可能需要配置如何启动、如何等待等。在网络上必须有大量使用 boost:asio 的示例,这些示例涉及配置您在此处描述的内容,即工作组范式。我在 SO 上看到 boost::asio 一个 TON,因此可能还有许多相关或接近相关的问题。

如果它没有任何用处,请随时降级,如果是这种情况,我深表歉意。

于 2012-09-08T09:21:35.367 回答