之前在一篇文章中提到过线程的安全终止的方法,大致的意思就是自定义一个boolean 类型的 volatile 变量,通过控制这个变量来终止线程。
class UiThread extends Thread { private volatile boolean isRun = true; @Override public void run() { while (isRun) { //你的操作 } } public void close() { isRun = false; } }
但是这种做法有个弊端,那就是这种终止方法的实时性很低。
如果在while里面的代码执行时间很长,比如需要10分钟,但是在这10分钟内,调用了close方法,isRun变成了false,可是这时候程序运行到while括号里面的代码段,只有运行完这个括号里面的代码段,才会判断isRun,这样从调用close进行终止,到程序实际终止的时延很大,对于一些实时性要求高,或则是事务类型的操作这样显然是不行的。
因此,本文再介绍一种实时性比较好的做法,使用interrupt,以前也一直没看明白,今天总算搞懂了。。。
首先,看看 Thread的interrupt方法解释:
void java.lang.Thread.interrupt() Posts an interrupt request to this Thread. The behavior depends on the state of thisThread: Threads blocked in one of Object's wait() methods or one ofThread's join() or sleep() methods will be woken up, their interrupt status will be cleared, and they receive anInterruptedException. Threads blocked in an I/O operation of an java.nio.channels.InterruptibleChannel will have their interrupt status set and receive anjava.nio.channels.ClosedByInterruptException. Also, the channel will be closed. Threads blocked in a java.nio.channels.Selector will have their interrupt status set and return immediately. They don't receive an exception in this case. See Also: Thread.interrupted Thread.isInterrupted
大致的意思是,发送一个中断请求,但是针对不同的线程运行状态会有不同的反应:
1、如果线程阻塞在wait、join、sleep方法中,那么它会被唤醒,中断状态会被清空,并且收到InterruptedException
2、如果线程阻塞在IO操作java.nio.channels.InterruptibleChannel中,那么中断状态会被设置并且接受到java.nio.channels.ClosedByInterruptException异常
3、如果线程阻塞在java.nio.channels.Selector中,那么中断状态会被设置并且立即返回,但是不会收到异常信号。
看到这,其实我以为正常的终止线程和开启线程的方法应该是这样的
开启
thread = new UiThread(); thread.start();
关闭
thread.interrupt();
run方法
class UiThread extends Thread { @Override public void run() { while (!interrupted()) { //你的操作 } } }
判断的标志位可以才用!interrupted()方法去判断,也可以采用isInterrupt()方法去判断,二者的区别是前奏会清空FLAG,后者不会。
但事实上,仅仅这样不一定能终止不的了线程,还是要看线程run方法里面具体是什么操作。
1、如果线程处于wait、join、sleep这几种状态,应该这么写
public void run() { Log.i(TAG, "Start Thread."); try { while (!interrupted()) { Log.i(TAG, "Running."); sleep(3000); } } catch (InterruptedException e) { Log.i(TAG, "InterruptedException."); } Log.i(TAG, "Stop Thread."); }
或者
while(!interrupted()){ Log.i(TAG,"Running."); try{ sleep(3000); }catch(InterruptedException e){ // TODO Auto-generated catch block break; } Log.i(TAG,"Stop Thread."); }
而针对第2、3种情况,正常书写就行
class UiThread extends Thread { @Override public void run() { while (!interrupted()) { //IO操作等 } } }