std::thread 创建线程的几种方式

简介

本文主要介绍标准C++中 thread的创建线程的几种方式。

使用时需要加头文件:

#include <thread>

位于std命名空间中,是跨平台的线程操作

 

使用说明

1、通过函数指针创建

一般来说,像CreateThread、_beginthread等创建线程时,都会先写一个含有一个参数(LPVOID lpParam)的全局函数,用于通过函数指针创建线程。

在标准C++提供的 thread方法中,函数指针的方式也需要一个全局函数,不过参数个数已经不再受限制

比如

void func(int param1,int param2,int param3);//全局函数

thread t(func,param1,param2,param3);//创建线程

此种方式通过参数的形式传递线程数据

 

2、通过函数对象创建

通过构建一个函数对象传给thread,以创建线程,因为函数对象的创建方式多样,所以对应创建线程的方式也有多种,具体参照示例代码。

通过函数对象,可以向函数对象类添加成员变量,并初始化和使用这些变量,以传递线程数据

 

3、通过lamda表达式创建

构建一个lambda表达式创建线程,通过lambda参数传递数据。

 

4、通过成员函数创建

通过成员函数创建线程,可以在不同的线程中执行对象的方法。在多线程中,如果访问同一个对象,需要保证线程安全,避免竞争条件。

 

示例代码
 


#include <iostream>

#include <thread>

 

using namespace std;

 

void counter( int id, int numIter )

{

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

    {

        cout << "counter id:" << id << endl;

        cout << "iteraion:" << i << endl;

    }

}

 

//通过函数指针创建线程

int main1()

{

    thread t1( counter, 1, 6 );

    thread t2( counter, 2, 4 );

 

    //如果没有join,main函数加载两个线程后立即结束,导致线程也中止

    //可以确保主线程一直运行,直到两个线程都执行完毕

    t1.join();

    t2.join();

 

    //从不同线程中访问cout是线程安全的,没有任何数据竞争

    //即使没有数据竞争,不同线程的输出仍然可以交错(可以通过同步解决)

    system( "pause" );

    return 0;

}

 

class CCount

{

public:

    CCount( int id, int numIter ): m_ID( id ), mNum( numIter )

    {

 

    }

 

    void operator()()const

    {

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

        {

            cout << "counter id:" << m_ID << endl;

            cout << "iteraion:" << i << endl;

        }

    }

private:

    int m_ID;

    int mNum;

};

 

//通过函数对象创建线程

int main2()

{

    //方法1

    thread t1{ CCount{1, 20} };

    t1.join;

 

    //方法2

    CCount c( 2, 12 );

    thread t2( c );

    t2.join();

 

    //方法3

    thread t3( CCount( 3, 10 ) );

    t3.join();

 

    system( "pause" );

    return 0;

}

 

//通过lambda创建线程

int main3()

{

    int id = 1;

    int numIter = 10;

 

    thread t1( [id, numIter]

    {

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

        {

            cout << "counter id:" << id << endl;

            cout << "iteraion:" << i << endl;

        }

    } );

    t1.join();

    system( "pause" );

    return 0;

}

 

class MyClass

{

public:

    MyClass( int id = 0, int nNum = 0 ) : m_ID( id ), mNum( nNum )

    {

 

    }

    ~MyClass() = default;

 

    void func()

    {

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

        {

            cout << "counter id:" << m_ID << endl;

            cout << "iteraion:" << i << endl;

        }

    }

 

private:

    int m_ID;

    int mNum;

};

 

//通过成员函数创建线程

int main()

{

    MyClass mc( 1, 5 );

    thread t1( &MyClass::func, &mc );

    t1.join();

    system( "pause" );

    return 0;

}

 


//#include <cstdlib>

//#include <cstdio>

//#include <cstring>

#include <string>

#include <iostream>

#include <thread>

using namespace std;

 

#pragma region C++11 thread基本创建方法

 

#if 1

// 案例一

void my_print()

{

	cout << "线程开始执行了!" << " thread ID= " << std::this_thread::get_id() << endl;

	//...

	//...

	cout << "线程结束执行了!" << " thread ID= " << std::this_thread::get_id() << endl;

}

 

// 案例二

class TA

{

public:

	TA()

	{

		cout << "TA构造函数执行" << this << " thread ID= " << std::this_thread::get_id() << endl;

	}

	~TA()

	{

		cout << "~TA析构函数执行" << this << " thread ID= " << std::this_thread::get_id() << endl;

	}

 

	// 案例二

	void operator()()	// 不带参数    必须重载()  因子线程需运行函数

	{

		cout << "线程operator开始执行了!" << this << " thread ID= " << std::this_thread::get_id() << endl;

		//...

		//...

		cout << "线程operator结束执行了!" << this << " thread ID= " << std::this_thread::get_id() << endl;

	}

 

	TA(const TA& ta)

	{

		cout << "TA拷贝构造函数执行:" << this << " thread ID= " << std::this_thread::get_id() << endl;

	}

 

	// 案例四

	void thread_fun()

	{

		cout << "thread_fun执行:" << this << " thread ID= " << std::this_thread::get_id() << endl;

	}

};

 

int main()

{

	// 案例一 直接用函数当对象

	//std::thread thobj(my_print);

	thobj.join();

	//bool b = thobj.joinable();

	//thobj.detach();

	//b = thobj.joinable();

 

	// 案例二 直接用类对象当对象

	TA t;

	//std::thread thobj2(t);

	std::thread thobj2(std::ref(t));  // 注意这两种的区别 std::ref直接引用原对象,少了一次拷贝和析构

	thobj2.join();		 // 此时子线程拷贝的对象 析构函数会在前台运行

	//thobj2.detach();	// 此时子线程拷贝的对象 析构函数会在后台运行

 

	// 案例三 lambda表达式

	//auto my_thread = [] {

	//	cout << "lambda线程开始执行了!" << endl;

	//	//...

	//	//...

	//	cout << "lambda线程结束执行了!" << endl;

	//};

	//auto my_thread1 = []()->void {

	//	cout << "lambda线程开始执行了!" << endl;

	//	//...

	//	//...

	//	cout << "lambda线程结束执行了!" << endl;

	//};

 

	//std::thread thobj3(my_thread);

	//thobj3.join();

 

	//std::thread thobj4([] {

	//	cout << "lambda线程开始执行了!" << endl;

	//	//...

	//	//...

	//	cout << "lambda线程结束执行了!" << endl;

	//});

 

	//thobj4.join();

	//案例四 使用类成员函数作为线程函数

	//TA t;

	//std::thread thobj5(&TA::thread_fun, &t);

	//thobj5.join();

 

	printf("hello jadeshu...\n");

	//system("pause");

	return 0;

}

#endif

#pragma endregion C++11 thread基本创建方法

 

#pragma region 线程传参实例应用

 

//void my_print(const int num, const string &buf)

//{

//	cout << num << endl;

//	cout << buf << endl;

//}

//

//int main()

//{

//	//一、传递临时对象作为线程参数

//	int var = 20;

//	int& my_var = var;

//	char my_buf[] = "this is main.cpp";

//	std::thread thobj1(my_print,my_var,string(my_buf));

//	thobj1.detach();

//	//thobj1.join();

//

//	printf("hello jadeshu...\n");

//	//system("pause");

//	return 0;

//}

#pragma endregion 线程传参实例应用

 

// 函数调用操作符的声明与定义.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream>
#include <thread> //用于管理线程的函数和类在<thread>中声明,而那些保护共享数据的函数和类在其它头文件中声明.
using namespace std;

void do_something()
{//每个线程都必須具有的一个初始函数(initial fun)
	std::cout << "do_something()\n";
}

void do_something_else()
{//每个线程都必須具有的一个初始函数(initial fun)
	std::cout << "do_something_else()\n";
}

class background_task
{
public:
	void operator()() const
	{ //函数调用操作符的声明与定义
		do_something();
		do_something_else();
	}
};


//通过成员函数创建线程
class MyClass
{
public:
	MyClass(int id = 0, int nNum = 0) :m_ID(id),mNum(nNum)
	{     
	}
	~MyClass() = default;

	void func()
	{
		for (int i = 0; i < mNum; ++i)
		{
			cout << "counter id:" << m_ID << endl;
			cout << "iteraion:" << i << endl;
		}
	}
private:
	int m_ID;
	int mNum;
};

int _tmain(int argc, _TCHAR* argv[])
{
	background_task f;
	std::thread my_thread(f);//my_thread(f),将一个带有函数调用操作符的类的实例传递给std::thread的构造函数,是一个经常使用的编程实践.
	my_thread.join();

	MyClass mc(1, 5);    
	thread t1(&MyClass::func,&mc);    
	t1.join();    

	system("pause");
	return 0;
}






 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

隨意的風

如果你觉得有帮助,期待你的打赏

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值