Thread构造函数?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Thread构造函数?相关的知识,希望对你有一定的参考价值。

Thread thread1 = new Thread(t1, "加线程1");
Thread thread2 = new Thread(t1, "加线程2");
Thread thread3 = new Thread(t2, "减线程1");
Thread thread4 = new Thread(t2, "减线程2");
这几行代码什么意思?

参考技术A 分别新建了Thread类的对象thread1、thread2、thread3、thread4对象,里面是两个参数,这两个参数的具体作用还要看Thread类中是怎么使用的才能知道追问

程序代码里没有Thread类代码。应该是直接继承类库里的吧?
http://wenda.so.com/q/1373361565064540
这是那段代码的地址

本回答被提问者采纳

没有参数的 std::thread 构造函数

【中文标题】没有参数的 std::thread 构造函数【英文标题】:std::thread constructor with no parameter 【发布时间】:2016-01-27 12:42:49 【问题描述】:

根据cppreference.com, std::thread没有参数的构造函数表示:

创建不代表线程的新线程对象。

我的问题是:

    为什么我们需要这个构造函数?如果我们使用这个构造函数创建一个thread,我们以后如何“分配”一个线程函数? 为什么我们没有一个“run(function_address)”方法,这样当不带参数构造时,我们可以为 thread 指定一个函数来“运行”。 或者,我们可以构造一个带有可调用参数(函数、函子等)的thread,但稍后调用“run()”方法来实际执行线程。为什么std::thread不是这样设计的?

【问题讨论】:

线程是可移动的,因此可以交换。 【参考方案1】:

您的问题表明可能存在一些混淆,将 执行线程 的概念与 std::thread 类型清楚地分开,并将两者与“线程函数”。

执行线程表示通过您的程序的控制流,可能对应于内核管理的操作系统线程。 std::thread 类型的对象可以与一个执行线程相关联,或者它可以是“空的”并且不引用任何执行线程。 标准 C++ 中没有“线程函数”这样的概念。通过将任何函数传递给std::thread 对象的构造函数,任何函数都可以在新的执行线程中运行。
    为什么我们需要这个构造函数?

构造不涉及执行线程的空状态。您可能希望拥有一个类的成员变量 std::thread,但不希望立即将其与执行线程相关联。。所以你默认构造它,然后启动一个新的执行线程,并将它与std::thread 成员变量相关联。或者你可能想这样做:

std::thread t;
if (some_condition) 
  t = std::thread func1, arg1 ;

else 
  auto result = some_calculation();
  t = std::thread func2, arg2, result ;

默认构造函数允许创建对象t,而无需启动新的执行线程直到需要。

如果我们使用这个构造函数创建一个线程,我们以后如何“分配”一个线程函数呢?

您使用“分配”来“分配”:-)

但是您没有为其分配“线程函数”,这不是std::thread 的用途。你为它分配另一个std::thread

std::thread t;
std::thread t2 func, args ;
t = std::move(t2);

考虑创建一个新的执行线程,而不是“分配一个线程函数”给某物。您不只是分配一个函数,这就是 std::function 的用途。您正在请求运行时创建一个新的执行线程,该线程将由std::thread 对象管理。

    为什么我们没有一个“run(function_address)”方法,这样当不带参数构造时,我们可以指定一个函数来为那个线程“运行”。

因为你不需要它。您可以通过构造带有参数的std::thread 对象来启动新的执行线程。如果您希望该执行线程与现有对象相关联,则可以通过移动分配或交换来实现。

    或者,我们可以构造一个带有可调用参数(函数、函子等)的线程,但稍后调用“run()”方法来实际执行该线程。为什么 std::thread 不是这样设计的?

为什么要这样设计?

std::thread 类型用于管理一个执行线程,该线程不持有供以后使用的可调用对象。如果您想创建一个可调用对象,以后可以在新的执行线程上运行,在 C++ 中有很多方法可以做到这一点(使用 lambda 表达式,或std::bind,或@987654336 @,或std::packaged_task,或自定义函子类型)。 std::thread 的工作是管理一个执行线程,在你想调用它之前不要持有一个可调用对象。

【讨论】:

【参考方案2】:

提供了默认构造函数,以便可以创建“空”thread 对象。在构造所述对象时,并非所有thread 对象都将与执行线程相关联。考虑thread 是某个类型的成员并且该类型具有默认构造函数的情况。考虑另一种情况,thread 类型没有“挂起”线程的概念,即它不能在挂起状态下创建。

thread 类型没有某种“运行”方法,因为最初的设计决策 (IIRC) 之一是在 thread 对象和执行线程之间建立“强”关联.允许threads 被“移动”使这个意图更清晰(在我看来)。因此,将thread 对象的实例移动到“空”对象比尝试“运行”thread 更清晰。

可以想象,您可以创建一个提供“运行”方法的某种包装类,但我认为这可能是一个更窄的用例,并且可以通过@987654330 的 API 解决 @类

【讨论】:

谢谢@Niall,但为什么最初的设计偏爱“强”关联?它有什么好处? 当时的很多讨论都是围绕在对象超出范围后如何处理“未连接”线程?鉴于对做什么没有真正的共识,因此调用std::terminate 的结果是因为它提供了“最安全”的结果。 IE。如果程序员打算将其从正在运行的线程中分离出来,那么他们需要对此进行明确说明,并且析构函数中的“连接”可能会导致意外死锁。【参考方案3】:

默认构造函数使您可以创建线程数组:

thread my_threads[4];

for (int i=0; i<4; i++)

   thread temp(func,...);
   my_threads[i]=move(temp);

使用默认构造函数创建的线程“成为”具有移动构造函数的“真实”线程。

如果您需要/喜欢,您可以将线程与标准容器一起使用。

【讨论】:

【参考方案4】:

编辑:也许让我们先评论最后一部分:

3.2 为什么std::thread不是这样设计的?

我不知道究竟是为什么(肯定有优点和缺点 - 请参阅 Jonathan Wakely 的回答以获取有关其背后理性的更多详细信息),但似乎 c++11 std::thread 的建模更接近 pthreads比例如QT 或 Java 的 QThread/Thread 类,这可能是您困惑的根源。

关于你的其他问题:

1.1 为什么我们需要这个构造函数?

您可能想创建一个std::thread 变量,但不要直接启动线程(例如,类成员变量或静态数组的元素,如alangab 所示)。它与无需文件名即可创建的std::fstream 没有太大区别。

1.2 如果我们使用这个构造函数创建一个线程,我们以后如何“分配”一个线程函数?

例如:

std::thread myThread;

// some other code

myThread = std::thread(foo()); 
    为什么我们没有一个“run(function_address)”方法,这样当不带参数构造时,我们可以指定一个函数来为那个线程“运行”。

我不知道为什么要这样设计,但我看不出run 方法与上述语法相比有什么好处。

3.1 或者,我们可以构造一个带有可调用参数(函数、函子等)的线程,但稍后调用“run()”方法来实际执行线程。

您可以通过创建 lambda 或 std::function 对象来模拟这一点,并在您想要运行该函数时创建线程。

auto myLambda = [=]foo(param1, param2);;
// some other code
std::thread myThread(myLambda);

如果您想使用您描述的语法,我建议您编写自己的 Thread 包装类(应该只需要几十行代码),它(可选)还可以确保线程是分离的或在破坏包装器时加入,在我看来,这是 std::thread 的主要问题。

【讨论】:

以上是关于Thread构造函数?的主要内容,如果未能解决你的问题,请参考以下文章

std::thread 按引用传递调用复制构造函数

std::thread,类构造函数和析构函数

Java thread类构造方法问题

Thread 构造方法

c++11的std::thread能用类的成员函数构造一个线程吗?语法怎样?

在类构造函数线程中启动 std::thread 是不是安全?