我正在寻找一种方法(最好使用 boost 线程),以在线程尚未加入时中断该线程。我启动了多个线程,并希望结束所有未在 200 毫秒内完成的线程。我试过这样的事情
boost::thread_group tgroup;
tgroup.create_thread(boost::bind(&print_f));
tgroup.create_thread(boost::bind(&print_g));
boost::this_thread::sleep(boost::posix_time::milliseconds(200));
tgroup.interrupt_all();
现在可以了,所有线程在 200 毫秒后结束;但是,如果这些线程在 200 毫秒之前完成,我想尝试加入这些线程,如果在一定时间内未完成,是否有办法加入并中断?
编辑:我需要在超时前加入的原因:
我正在创建一个速度非常重要的服务器。不幸的是,我必须向其他服务器请求一些信息。所以我想并行进行这些调用,并尽快完成。如果服务器花费的时间太长,我只能忽略来自该服务器的信息,并在没有它的情况下继续。所以我的超时时间是我可以等待的最长时间。能够在收到所有响应时继续沉思,而不是等待时间超时计时器,这对我来说将是非常有益的。那么我的程序将:
-从客户端获取请求。
-解析信息。
创建线程
-将信息发送到多个其他服务器。
-从服务器获取信息。
-将来自服务器的信息放在共享队列中。
结束话题
-从共享队列中解析信息。
-返回信息给客户端
最佳答案
您想要使用的可能是一组作用域线程,并在超时后对所有剩余线程调用终止。不幸的是,线程组和作用域线程不能一起使用。
线程组类实际上是一个非常简单的容器:如果您还没有指向它的线程,则无法删除它的线程,并且您无法获得指向由该组创建的线程的指针。类 API 也没有提供太多。在您的情况下,这对管理来说有点阻碍。
其余解决方案依赖于在组外创建线程,并让每个线程在完成之前执行特定任务。它可以:
- 将自己从组中移除,
- 然后将自己添加到另一个组
管理线程必须在后面的组上调用 join_all
,并像以前一样处理前者。
using namespace boost;
void thread_end(auto &thmap, thread_group& t1, thread_group& t2, auto &task){
task();
thread *self = thmap[this_thread::get_id()];
t1.remove_thread(&self);
t2.add_thread(&self);
}
std::map<thread::id, thread *> thmap;
thread_group trunninggroup;
thread_group tfinishedgroup;
thread *th;
th = new thread(
bind(&thread_end, thmap, trunninggroup, tfinishedgroup, bind(&print_f)));
thmap[th->get_id()] = th;
trunninggroup.add_thread(th);
th = new thread(
bind(&thread_end, thmap, trunning_group, tfinishedgroup, bind(&print_g)));
thmap[th->get_id()] = th;
trunninggroup.add_thread(th);
boost::this_thread::sleep(boost::posix_time::milliseconds(200));
tfinishedgroup.join_all();
trunninggroup.interrupt_all();
但是如果您真的希望管理线程在线程结束实际发生时得到通知(而且我不确定它是否有任何用处),这并不理想。获得通知的解决方案可能是:
- 如上进行组迁移
- 然后触发一个条件变量,管理线程在该变量上执行
timed_wait
但是你必须做一些时间计算来跟踪收到通知后的剩余时间,并在剩下的时间继续 sleep 。这将完全取决于用于该任务的 Duration 类。
更新
从大局来看,我会尝试一种完全不同的方法:我不认为终止一个已经完成的线程是个问题,所以我会将它们全部留在组中,并使用组来创建它们,如您的代码所示。
但是,我会尝试在所有 线程完成后或超时后立即唤醒管理线程。这对于 thread_group
类单独提供的功能是不可行的,但它可以通过定制的信号量或 boost::barrier
的补丁版本来完成,以允许定时等等。
基本上,您为组中的线程数加上一个(主线程)设置了一个障碍,并让主线程时间等待它。每个工作线程执行其工作,完成后,将其结果发布到队列中,并在屏障上等待
。如果所有工作线程都完成了他们的任务,每个人都将等待并触发屏障。
然后主线程(以及所有其他线程,但这并不重要)被唤醒,可以通过终止组并处理结果来继续。否则,它会在超时时被唤醒,并且无论如何都会做同样的事情。
boost::barrier
的修补应该不会太难,你应该只需要复制wait
方法并替换条件变量wait
inside by a timed_wait
(我没有看代码,虽然这个假设可能完全正确)。否则我为 this question 提供了一个示例信号量实现,这应该也不难修补。
一些最后的考虑:终止一个线程通常不是最好的方法。相反,您应该尝试向线程发出信号,让它们必须中止,并等待它们,或者以某种方式让它们将未完成的任务传递给辅助线程,辅助线程应该串行清理。然后您的线程组将准备好处理下一个任务,并且您不必一直销毁和创建线程,这是一项代价高昂的操作。它将需要在您的应用程序上下文中形式化任务的概念,并使线程在循环中运行以接受新任务并处理它们。
关于c++ - 如果没有加入则中断线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15929258/