您的位置:首页 > 其它

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

2015-05-19 21:26 323 查看
引起线程变为阻塞状态的原因有:

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

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

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

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

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

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

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

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

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

[cpp] view
plaincopy

#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()如何退出,对象的析构都会被调用。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: