为什么80%的码农都做不了架构师?>>>
在说明之前先介绍一些关于中断的情况
第一、线程终止满足以下情况任意一种即可:
1、run方法体执行完最后一条语句
2、run方法中由return语句返回时
3、捕获到异常,catch中结束时或出现未捕获异常时
第二、与Thread中断相关的api有:stop与suspend已经不建议使用不再分析,为了稳定性,也建议大家不要使用
public void interrupt()
public static native boolean interrupted();
public static native boolean isInterrupted();
这三个API很相似,看着很晕,但是都是围绕Thread的一个属性来说的,有一个boolean类型的属性来表明线程是否被中断。
interrupt()方法返回void,将该属性置为true,并发送一个信号,睡眠会被提前终止,想起Thread的sleep方法了吗?sleep中,如果调用该方法,会直接抛出异常,终止睡眠,意图尽早结束程序,这也是该方法本质
interrupted()方法返回当前该属性的状态,后将该属性置为false,清除线程的中断状态
isInterrupted()仅仅返回该属性
可以看出这些api都不会使线程中断,而只是改变一个属性值,中断需要自己去操作
下面进入正题,如何中断线程:
1、使用interrupt()中断线程
看下面的例子
Thread thread1; public void add(View view) { thread1=new Thread(new Task()); thread1.start(); } public void cancle(View view) { thread1.interrupt(); } class Task implements Runnable{ @Override public void run() { int a=0; while (!Thread.currentThread().isInterrupted()){ a++; Log.e(tag,Thread.currentThread().getId()+":"+a); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); Log.e(tag,Thread.currentThread().getId()+":"+a); } } } }
然而当我点击取消时,发现没有任何作用,前面不是说interrupt()将状态置为true了吗,为什么循环还在继续?这是因为Thread.sleep在抛出InterruptedException前Java虚拟机会先将线程的中断标识位清除,因此只要在catch中再次调用interrupt(),就不会进入循环。
2、1的变体循环条件为while (!thread1.interrupted()),不过不建议这样,因为会改变那个布尔值,影响别处的操作
public void add(View view) { thread1=new Thread(new Task()); thread1.start(); } public void cancle(View view) { thread1.interrupt(); } class Task implements Runnable{ @Override public void run() { int a=0; while (!thread1.interrupted()){ a++; Log.e(tag,Thread.currentThread().getId()+":"+a); try { Thread.sleep(1000); } catch (InterruptedException e) { Log.e(tag,Thread.currentThread().getId()+":"+a); Thread.currentThread().interrupt(); } } } }
3、除了1、2中的方法,还可以自己定义布尔变量,该变量必须定义为volatile,或者所有对它的访问必须同步(synchronized) (当然啦,单线程自控时可不用),但是自己定义的布尔类型不是受到interrupt()的影响,只能在下一次判断中停止,而不能更早的退出当前的阻塞状态。