线程对象属于一次性消耗品,一般线程执行完run方法之后,线程就正常结束了,不能再次start,只能新建一个线程对象。
所以正常退出run方法,一般就能正常结束线程。在很多情况下,run中都有循环,所以我们只要跳出循环,让run方法执行完,也就正常终止了线程
对于线程的终止,经过查询资料,大部分人提到了三种方法,就先说这三种
1.使用标志位来退出
2.使用interrupt()方法(注意,不是interrupted)
3.stop()方法
第一种:使用标志位来退出(volatile保证了只有一个线程在操作exit)
class MyThread extends Thread {
public volatile boolean exit = false;
public void run() {
while (!exit) {
Log.e("Thread", "running");
try {
Thread.sleep(5000);
threadSafe.exit=true;
} catch (InterruptedException e) {
e.printStackTrace();
break;
}
}
Log.e("Thread", "stop");
}
}
第二种:使用interrupt()方法
分两种情况:阻塞情况和正常情况
阻塞情况:
例如线程休眠时,使用interrupt()方法来抛出InterruptedException异常,在catch中break出循环
当阻塞状态时,如果有interrupt()发生,系统除了会抛出InterruptedException异常外,还会调用interrupted()函数,调用时能获取到中断状态是true的状态,调用完之后会复位中断状态为false,所以异常抛出之后通过isInterrupted()是获取不到中断状态是true的状态,从而不能退出循环。即阻塞状态下只能用break来推出,而不是标志位。
class MyThread extends Thread {
public void run() {
while (true) {
Log.e(TAG, Thread.currentThread()+"running");
try {
Thread.sleep(5000);
threadSafe.interrupt();
} catch (Exception e) {
e.printStackTrace();
Log.d(TAG, "in to exception");
break;
}
}
Log.e(TAG, "stop");
}
}
正常情况
public void run() {
while (!isInterrupted()) {
Log.e("in Thread", Thread.currentThread()+"running");
threadSafe.interrupt();
}
Log.e(TAG, "stop");
}
}
由此可以看到,interrupt()方法把线程的isInterrupted的属性从false改变为true
一般情况:
在正常状态下使用isInterrupted()作为标志位来退出,在阻塞状态下通过捕获异常来退出。因此使用interrupt()来退出线程的最好的方式应该是两种情况都要考虑:
也就是说
class MyThread extends Thread {
public void run() {
while (!isInterrupted) {//正常状态通过标志位退出
Log.e(TAG, Thread.currentThread()+"running");
try {
Thread.sleep(5000);//阻塞状态通过break退出
} catch (InterruptedException e) {
e.printStackTrace();
Log.d(TAG, "in to exception");
break;
}
}
Log.e(TAG, "stop");
}
}
第三种:使用stop来推出,会出现问题,不建议使用