前段时间去面试了百度android职位,虽然没有通过,但是发现了很多自己的不足,回来痛定思痛,决定将所有的面试题整理到CSDN上,查漏补缺。
问:如何停止一个线程?
由于平时不怎么写多线程,所以直接说了个interrupt()显然是不对的。那么接下来我们探讨一下java中如何停止一个线程。
Thread.stop()
该方法已经不推荐使用,它不能保证安全的退出线程,这里不讨论。
interrupt()方式
我们先来学习下线程的interrupt()、interrupted()、isInterrupted()方法的区别
interrupt():作用是中断本线程,是实例方法
这里的中断线程,并非真正的把线程终止,而是将“中断标记”设置为true。
在本线程内,中断自身是允许的:将“中断标记”设置成true
其他线程中调用本线程的interrupt(),会通过checkAccess()检查权限,可能抛出SecurityException()异常。
若本线程当前是阻塞状态,调用interrupt()后,它的“中断线程”状态被清除,并收到InterruptException异常
若本线程当前是运行状态,则会将中断标记设置为true。
interrupted()方法:判断当前线程是否处于中断状态,是Thread的静态方法,如下:
public static boolean interrupted() {
return currentThread().isInterrupted(true);
}
isInterrupted()方法:判断调用线程是否处于中断状态,是实例方法
例如:
public static void main(String[] args){
Thread thread = new Thread(()->{}); //定义一个线程,伪代码没有具体实现
thread.isInterrupted();//判断thread是否处于中断状态,而不是主线程是否处于中断状态
Thread.isInterrupted(); //判断主线程是否处于中断状态
}
那么,接下来,我们探究如何停止一个线程
使用调用需要被中断的线程的interrupt()方法,在需要被中断的线程run()方法中使用isInterrupted()判断,并catch InterruptException异常来carry需要被中断的线程是阻塞的情况。代码如下:
public class StopThreadDemo {
public static void main(String[] args) throws InterruptedException {
NeedStopThread thread = new NeedStopThread();
thread.start();
//主线程sleep,此时子线程在运行
Thread.sleep(300);
//在主线程中调用thread.interrupt();终端该线程
thread.interrupt();
Thread.sleep(300);
System.out.println("is interrupted:"+thread.isInterrupted());
}
}
class NeedStopThread extends Thread {
@Override
public void run() {
try {
//这里可以直接写成while(!isInterrupted)为了打印这样写
while (true) {
//记录当前中断情况
boolean isInterrupted = isInterrupted();
System.out.println("isInterrupted:"+isInterrupted);
if (!isInterrupted) {
//处理业务
//Thread.sleep(5); 1处
}else{
break;
}
}
} catch (Exception e) {
System.out.println("catch e"+e.toString());
//carry线程阻塞时,外部调用interrupt()抛出的interruptedException
}
}
}
结果:
isInterrupted:false
isInterrupted:false
isInterrupted:false
isInterrupted:false
isInterrupted:false
isInterrupted:false
isInterrupted:false
isInterrupted:true
is interrupted:false
若放开注释1处,结果如下:
isInterrupted:false
isInterrupted:false
isInterrupted:false
isInterrupted:false
catch ejava.lang.InterruptedException: sleep interrupted
is interrupted:false
因为当外部(主线程)调用thread.interrupt()时,thread正在运行,而运行的内容是sleep(阻塞)当前线程。所以会抛出异常。这也符合我们上述所说:当需要被中断的线程是阻塞状态。外部调用thread.interrupt(),会抛出InterruptedException异常