zthread学习 实例九 任务终止(二)——中断方式

 

引起线程变为阻塞状态的原因有:

1、调用了sleep(),线程进入休眠状态。

2、调用了wait(),挂起了线程的运行。

3、线程正在等待某个I/0操作完成(此时中断是不会出现的)。

4、线程在尝试进入一段被一个互斥锁保护的代码块,而那个互斥锁已经被其他线程获得。

 

终止一个阻塞线程和终止一个非阻塞线程的方式有很大的不同。

 

终止一个阻塞线程 通常 的做法是,首先唤醒它,然后按终止一个非阻塞线程的方式来终止,但这样线程会多执行了一些代码。

 

有时需要在某个线程处于阻塞状态时 立即 终止它。ZThread库使用抛异常的方式来解决立即终止 阻塞 线程。因为从被阻塞的任务中离开时,可能需要销毁与之相关的对象并清理有关资源,正因为这样在run()中间跳出更像是抛出一个异常。在run()函数包含try模块,在响应异常的catch语句中清理有关资源。

 

interrupt()函数用来给线程设置中断状态,一个使用了中断状态设置的线程,如果已经被阻塞或尝试进行阻塞时将会抛出一个Interrupted_Exception异常。当异常被抛出或调用了intertupted()时,中断状态重新被设置。

 

中断状态可以通过调用interrupt()进行设置。调用interrupted()来检查中断状态(不仅能告知interrupt()是否被调用,还会清除当前的中断状态,以确保不会两次通知正被中断的任务),interrupted()会用一个Interrupted_Exception异常来通知一个已经阻塞的线程,或用一个成功的返回值来通知一个非阻塞的线程。下面例子显示了当设置中断状态时,run()函数中处理阻塞和非阻塞两种可能性的情况:

#include "stdafx.h" #include "zthread/FastMutex.h" #include "zthread/CountedPtr.h" #include "zthread/Runnable.h" #include <iostream> #include <vector> #include <ctime> #include "Display.h" using namespace ZThread; using namespace std; const double PI = 3.1415926; const double e = 2.7182818; class NeedCleanup { public: NeedCleanup(int idn = 0) : id(idn) { cout << " NeedCleanup : " << id << endl; } ~NeedCleanup() { cout << " ~NeedCleanup : " << id << endl; } private: int id; }; class Blocked : public Runnable { public: Blocked() : d(0.0){} void run() { try { while (!Thread::interrupted()) { //point1 阻塞线程的终止 抛出异常退出 NeedCleanup(1); cout << "Sleep" <<endl; Thread::sleep(5000); //point2 非阻塞线程的终止 通过while()条件退出 NeedCleanup(2); cout <<"Calculating" <<endl; for (int i= 0; i <100000; i++) //大量运算,使之处于非阻塞的情况下 { d = d + (PI + e) / (double)i; } } cout << "exit via while() test" <<endl; } catch (Interrupted_Exception& e) { cout << "exit via Interrupted_Exception test" <<endl; cerr << e.what() <<endl; } } private: volatile double d; }; int _tmain(int argc, _TCHAR* argv[]) { try { Thread t(new Blocked); //Thread::sleep(2000); //阻塞线程的终止 Thread::sleep(5010); //非阻塞线程的终止 t.interrupt(); //发出中断 cin.get(); } catch (Synchronization_Exception& e) { cerr << e.what() <<endl; } return 0; } 

为了保证不因退出而出现不一致的状态,所有资源获取都应封装在基于的对象中,以便无论run()如何退出,对象的析构都会被调用。

 

你可能感兴趣的:(thread,exception,Class,任务)