总结:
- 通过interrupt设置线程的中断标志位,并不能直接终止该线程,而是被中断的线程根据中断状态自行处理。
- isInterrupted和interrupted都是检测线程是否被中断,区别在于isInterrupted可判断线程的中断情况,interrupted只能判断执行当前代码的线程的中断情况,且后者会重置线程标志位为false。
1.线程中断三个关键方法
1.1 void interrupt()
中断线程。线程B调用线程A的interrupt方法,设置中断标志位为true后,立即返回。至于线程A什么时候被中断,需要线程A自行决定。例如,线程A因为调用了wait,sleep,join方法被阻塞挂起后,线程B调用了A的interrupt方法,线程A会在会在上述阻塞方法处抛出InterruptedException异常。
1.2 boolean isInterrupted()
检测线程是否被中断,返回true/false。
1.3 boolean interrupted()静态方法
检测当前线程是否被中断,返回true/false。若发现当前线程被中断,则会清除中断标志。
内部实现:
return currentThread().isInterrupted(true);
2. 线程中断代码示例
2.1 使用isInterrupted优雅退出经典模式:
public void run(){
try{
while (!Thread.currentThread().isInterrupted() && ***){
//do work
}
}catch (InterruptedException e){
//thread was interrupted during sleep or wail or join
e.printStackTrace();
}finally {
//clean resources
}
}
2.2 使用interrupt中断线程代码实例:
public static void main(String[] args) throws InterruptedException{
Thread threadOne = new Thread(new Runnable() {
@Override
public void run() {
try{
System.out.println("Thread one start sleep 20 s");
Thread.sleep(20000);
System.out.println("Thread one sleep over");
}catch (InterruptedException e){
System.out.println("Thread one is interrupted while sleeping");
e.printStackTrace();
return;
}
System.out.println("Thread one leaving normaly");
}
});
threadOne.start();
Thread.sleep(1000);//主线程睡1秒
threadOne.interrupt();//设置标志位中断线程
threadOne.join();//让子线程运行结束
System.out.println("main thread run over ...");
}
输出:
Thread one start sleep 20 s
Thread one is interrupted while sleeping
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at com.evan.wj.ThreadTest$1.run(ThreadTest.java:10)
at java.lang.Thread.run(Thread.java:748)
main thread run over ...
2.3 对比Interrupted和isInterrupted区别
代码实例1:
public static void main(String[] args) throws InterruptedException{
Thread threadOne = new Thread(new Runnable() {
@Override
public void run() {
while (true);
}
});
threadOne.start();
threadOne.interrupt();//设置中断标志
System.out.println("第一次isInterrupted:"+threadOne.isInterrupted());//true
System.out.println("第一次interrupted:"+threadOne.interrupted());//false
System.out.println("第二次interrupted:"+threadOne.interrupted());//false
System.out.println("第二次isInterrupted:"+threadOne.isInterrupted());//true
System.out.println("main thread run over ...");
}
输出:
第一次isInterrupted:true
第一次interrupted:false
第二次interrupted:false
第二次isInterrupted:true
main thread run over ...
解释:
第一个true,很简单,因为先设置了线程中断标志位,后判断是否被中断,返回true。
第二个false,interrupted调用的是currentThread.isInterrupted(true),因此表示主线程的线程中断标志位,当然为false。
第三个false,同第二次一样。
第四个true,由于isInterrupted并不会清除线程中断标志位,因此返回的依旧是true。
代码示例2:实践表明interrupted会清除中断标志位
public static void main(String[] args) throws InterruptedException{
Thread threadOne = new Thread(new Runnable() {
@Override
public void run() {
while (!Thread.currentThread().interrupted()){//清除了中断标志位
}
System.out.println("线程内isInterrupted:"+Thread.currentThread().isInterrupted());
}
});
threadOne.start();
threadOne.interrupt();//设置中断标志
threadOne.join();
System.out.println("main thread run over ...");
}
输出:
线程内isInterrupted:false
main thread run over ...
解释:线程内部的interrupted重置了线程标志位,因此后面线程内的isInterrupted输出为false。