Thread

//Boost
#include<boost/thread/thread.hpp>
#define BOOST_THREAD_VERSION 4 //使用最新版本,含有1,2,3但只是为了兼容之前程序。
Thread库丰富强大的扩展功能但不在Thread中的未看。
//C++11
#include<thread>


1.Thread_Class简析

特点:

1.线程对象需要一个可调用物,而调用函数的对象默认是拷贝传参,因此要求可调用物和参数类型都支持拷贝构造。所以如果希望传递给线程引用值就要使用ref库进行包装,同时必须保证被引用对象在线程执行期间一直存在,否则会引发为定义行为。

 

2.线程对象在析构时会调用std::terminate 结束线程的执行,并不会关心线程是否执行完毕,所以要保证函数正确运行完毕必须调用join()等待线程执行函数或者调用detach()分离线程体。

3.Thread实例的析构会导致其表示线程强制终止?

可是测试证实不会!他是在线程中插入结束点等待它自动结束?若线程死锁或者啥的则不会结束,资源也不会释放。

 

4.Thread对象创建完毕就会执行,不提供Start(),但事实上它含有私有成员函数Start_thread()启动自己。

 

类摘要:

Class Thread
{	//不可拷贝
Public:
	Thread();
	Explicit thread(F f);	//传递可调用对象
	Thread(F f, A1 a1, A2 a2, ...);  	//传递可调用对象及参数 

	Thread(thread&&) noexcept;	//转移构造函数(C++11)
	Thread& operator = (thread&&)noexcept;	//转移赋值函数(C++11)

	Bool joinable() const;	//是否可join
	Void join();	//等待线程
	Void detach();	//分离线程

	Bool try_join_for(const duration& rel_time); //超时等待(非C++11)
	Bool try_join_until(const time_point& t);	//超时等待(非C++11)

	Void interrupt();	//中断线程(非C++11)
	Bool interruption_requested() const;	//判断是否被中断(非C++11)

	Class id;	//内部类线程ID
	Id get_id() const;	//获得线程id对象
	Native_handle_type native_handle();	//获得系统操作相关的handle

	Static unsigned hardware_concurrency();	//获得可并发核心数
	Static unsigned physical_concurrency();	//获得真实CPU核心数
};

namespace this_thread{
	Thread::id ger_id();	//获得线程ID对象
	Void yield();	//允许重复调度线程
	Void sleep_nutil(const time_point&t);	//睡眠等待
	Void sleep_for(const duration& d);	//睡眠等待
}


2.Start_Thread

explicit thread(const boost::function0<void>& threadfunc): 

boost::function0<void>可以简单看为:一个无返回(返回void),无参数的函数。这里的函数也可以是类重载operator()构成的函数;该构造函数传入的是函数对象而并非是函数指针,这样一个具有一般函数特性的类也能作为参数传入

 

用法:

#include<iostream>
#include<boost/thread/thread.hpp>
#include<boost/chrono.hpp>
#include<boost/bind.hpp>
#include <boost/ref.hpp>
using namespace std;
using namespace boost;

void Alloa(string name)
{
	cout << "Alloa! " << name << ". __ Asuna" << endl;
	/*for (int i = 0; i < 10; i++)
	{
	cout << i << ' ';
	}*/
}



class mycount
{
	int id;
public:
	mycount(int d = 0) :id(d){}
	void operator()()
	{
		cout << "Alloa ! " << id << endl;
	}
	void Say(string name)
	{
		cout << name << endl;
	}
};
class ForThread
{
	//类内创建线程
public:
	static void Hello()
	{
		this_thread::sleep_for(boost::chrono::milliseconds(10000));
		cout << "ForTHread::HELLO  类内线程" << endl;
	}
	static void start()
	{
		thread t(Hello);
		t.join();
	}
};
int main()
{
	cout << "此线程ID" << this_thread::get_id() << endl;
	//this_thread::sleep_for(boost::chrono::microseconds(100));//此线程睡眠100MS
	//this_thread::yield();//允许CPU调度让出执行权
	
	thread t1, t2;
	cout << t1.get_id() << endl;
	assert(t1.get_id() == t2.get_id());
	
	//*******************以下皆为拷贝传递**************************//

	// 1 /
	thread t1(&Alloa,"YWF");//都可
	thread t2(Alloa, "YWF");
	t1.detach();
	t1.join();

	/ 2 复杂对象作为参数
	mycount c(1); //必须重载()
	thread thrd1(c);//自动执行c();
	thrd1.join();

	/ 3 类内部创建线程 ///
	ForThread Forthrd;//可以设置成仅有一个实例可以运行的哦!
	Forthrd.start();//主线程会等待函数返回哦!

	/ 4 类内部函数在类外创建 
	mycount my(10);
	thread th2(boost::bind(&mycount::Say, &my,"ZGJ"));
	cout <<"th2.joinable = " <<th2.joinable() << endl;
	th2.join();

	///*****************引用传参********************************///
	string argv1 = "YWFAHX";
	thread th2(boost::bind(Alloa, boost::ref(argv1)));


	//this_thread::sleep_for(boost::chrono::milliseconds(1000));//此线程睡眠100MS
	cout << "END OF MAIN" << endl;
	return 0;
}



3.等待线程结束

Join等待线程

Thread的成员函数joinable可以判断thread对象是否标示了一个可执行的线程。

若joinable返回true,则可调用

一直阻塞等待直到线程结束

Join();  


阻塞等待一定的时间,然后返回,或者等待的线程完毕返回。

Try_join_for();
Try_join_until();

Detach分离线程 -- 将线程托管给系统,不受控制了!

Detach将thread对象与线程执行体手动分离,从此后thread对象不代表任何线程体

Joinable() == false ,从而失去对线程体的控制。

分离后的线程体将不受影响的继续执行,直到函数结束或者随着主线程一起结束。

所以不需要在操作线程体时可利用临时对象启动线程后即可分离。

Thread对象在析构时若其函数仍未执行完毕则自动detach。

 

Thread_guard()控制thread对象的析构时行为 类似的有scoped_thread()
Thread_guard()是与Lock_guard()类似的辅助类
#include<boost/thread/thread_guard.hpp>



4.中断/结束线程

中断依靠Interrupted()

通过interrupted_requested()检查是否被要求中断.

被中断的线程会抛出一个thread_interrupted异常(一个空类),应该捕获处理,否则默认动作是终止线程。

线程不是想中断就可以中断,需要等待中断点(手动设置)才可以触发。

Boost::Thread中12个中断点(函数)为
1. Thread::Join() 
2. thread::Try_join_for()
3. thread::try_join_until()
4. Condition_variable::Wait() 
5. Condition_variable::wait_for() 
6. Condition_variable::wait_until()
7. Condition_variable_any::wait()
8. Condition_variable_any::wait_for()
9. Condition_variable_any::wait_until()
10. This_thread::sleep_for()
11. This_thread::sleep_until()
12. This_thread::interruption_point()//不会等待,只起标签作用,到此处可被中断。

 

启用/禁用中断(选,我没仔细看)

默认线程是可被中断的

但是boost::this_thread里提供了一组函数与类来共同完成现成的中断启/禁用

Interruption_enabled() //检测当前线程是否可中断

Interrupted_requested() //检测当前线程是否被要求中断

类disable_interruption 是一个RAII类型的对象,在构造时关闭线程的中断,析构时自动回复线程的中断状态。在disable_interruption生命周期内线程不可中断,除非使用restore_interruption对象

Restore_interruption只可在disable_interruption的作用域内使用,它在构造时临时打开线程的中断状态,析构时又关闭中断状态。


Code:

#include<iostream>
#include<boost/thread/thread.hpp>
#include<boost/chrono.hpp>
#include<boost/bind.hpp>
using namespace std;
using namespace boost;


void Alloa(string name)
{
	try
	{
		using namespace this_thread;
		assert(interruption_enabled());//测试是否允许中断
		{
			disable_interruption dis;
			assert(!interruption_enabled());//此时不允许中断
			cout << "Alloa! " << name << ". __ Asuna" << endl;
			this_thread::sleep_for(chrono::milliseconds(2));
			interruption_point();
			//restore_interruption ri(dis);//下面的中断是否可用
			assert(interruption_enabled());//可用
			cout << interruption_enabled() << endl;
			interruption_point();
		}
		assert(interruption_enabled());
		cout << "END Alloa" << endl;
		interruption_point();
	}
	catch (const thread_interrupted)
	{
		cout << "thread_interrupted" << endl;
	}
}

int main()
{

	thread t1(Alloa, "YWF");
	//this_thread::sleep_for(chrono::milliseconds(1));
	t1.interrupt();
	assert(t1.interruption_requested());
	t1.join();
	return 0;
}