子线程:
void ThreadMain()
{
cout << "begin sub thread main " << this_thread::get_id() << endl;
for (int i = 0; i < 10; i++)
{
if (!is_exit) break;
cout << "in thread " << i << endl;
this_thread::sleep_for(chrono::seconds(1));//1000ms
}
cout << "end sub thread main " << this_thread::get_id() << endl;
}
main函数三种情况:
01:
int main(int argc, char* argv[])
{
{
thread th(ThreadMain);
}
getchar();
return 0;
}

explicit thread(_Fn&& _Fx, _Args&&... _Ax) {
using _Tuple = tuple<decay_t<_Fn>, decay_t<_Args>...>;
auto _Decay_copied = _STD make_unique<_Tuple>(_STD forward<_Fn>(_Fx), _STD forward<_Args>(_Ax)...);
constexpr auto _Invoker_proc = _Get_invoke<_Tuple>(make_index_sequence<1 + sizeof...(_Args)>{});
#pragma warning(push)
#pragma warning(disable : 5039) // pointer or reference to potentially throwing function passed to
// extern C function under -EHc. Undefined behavior may occur
// if this function throws an exception. (/Wall)
_Thr._Hnd =
reinterpret_cast<void*>(_CSTD _beginthreadex(nullptr, 0, _Invoker_proc, _Decay_copied.get(), 0, &_Thr._Id));
#pragma warning(pop)
if (_Thr._Hnd) { // ownership transferred to the thread
(void) _Decay_copied.release();
} else { // failed to start thread
_Thr._Id = 0;
_Throw_Cpp_error(_RESOURCE_UNAVAILABLE_TRY_AGAIN);
}
这是因为在使用函数指针做为thread的构造函数的参数时,会生成一个句柄 _Thr._Hnd ,这个句柄的生命周期与主线程一致,当主线程结束时该句柄也会被释放掉,由于此时子线程还在运行,因此将会出错
02
int main(int argc, char* argv[])
{
{
thread th(ThreadMain);
th.detach(); }
getchar();
return 0;
}
用detach()使子线程与主线程分离,相当于将子线程变成一个守护线程,将其资源如句柄的生命周期交给子线程
java的守护线程:
守护线程,是指在程序运行时 在后台提供一种通用服务的线程,这种线程并不属于程序中不可或缺的部分。通俗点讲,任何一个守护线程都是整个JVM中所有非守护线程的"保姆"。
用户线程和守护线程几乎一样,唯一的不同之处在于如果用户线程已经全部退出运行,只剩下守护线程存在了,JVM也就退出了。因为当所有非守护线程结束时,没有了被守护者,守护线程也就没有工作可做,当然也就没有继续执行的必要了,程序就会终止,同时会杀死所有的"守护线程",也就是说只要有任何非守护线程还在运行,程序就不会终止

03
int main(int argc, char* argv[])
{
{
thread th(ThreadMain);
th.detach(); //子线程与主线程分离 守护线程
//坑 :主线程退出后 子线程不一定退出,因此要注意子线程不要使用主线程中的变量
}
{thread th(ThreadMain);
this_thread::sleep_for(chrono::seconds(1));//模拟业务1000ms
is_exit = true; //通知子线程退出
cout << "主线程阻塞,等待子线程退出" << endl;
th.join();
//为了提高运行效率,在主线程业务逻辑处理结束才阻塞主线程,而不是子线程一加进来就阻塞主线程
cout << "子线程已经退出!" << endl;}
getchar();
return 0;
}
th.join()方法用于把子线程加入到主线程中,把主线程的CPU执行时间让子线程。比如在线程B中调用了线程A的Join()方法,直到线程A执行完毕后,才会继续执行线程B。在加入前CPU给两个线程都分的有时间片(线程是CPU调度的基本单位),再加入后这两个线程平分原本主线程的时间片。在std::thread t(func)后“某个”合适的地方调用,其作用是回收对应创建的线程的资源,避免造成资源的泄露。
用this_thread::sleep_for(chrono::seconds(1));来模拟业务1000ms,当主线程业务结束时需要使用is_exit = true;通知子线程结束,但由于时间片调度子线程不会一瞬间就结束,要使用th.join()来等待子线程结束,不然它的句柄被主线程释放了的话会出现问题。

可以看到创建了两个线程,由于并发的执行被显示在同一行了,
此外可以看到子线程中的in thread 0只显示了一行,与主线程业务逻辑运行时间吻合。