目录
一、引言
线程中断在开始没有特别重视,多线程往后学习才发现线程中断也是件比较有技巧的事情,停止线程不像break语句中那样简单,什么时候停止,停止后代码是否执行,如何捕捉线程异常都是我们需要学习的内容。
正常情况下我们停止线程有三种方法
-
使用退出标志,使线程正常退出,也就是当run方法完成后才停止;
-
就是我们上面所说的使用stop方法强行终止线程,是过期作废的方法,这种方法可以排除不用;
-
使用interrupt方法终止线程。
第一种比较常见这里建议使用第三种也重点讲第三种,以及为什么在第二种和第三种选择了第二种。
二、stop与interrupt
stop方法比较强势,直接把所用的停止,但是因为威力太强大所以我们不建议使用,举个例子
public class Testinterrupt {
public static void main(String [] args) {
Thread thread= new Thread(new Runnable() {
public void run() {
System.out.println(Thread.currentThread().getName()+"start");
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
System.out.println("线程中止");//线程终止后报异常
}
System.out.println(Thread.currentThread().getName()+"end");
}
});
System.out.println(Thread.currentThread().getName()+"start");
thread.start();
try {
Thread.sleep(2000);
//thread.interrupt();//中止线程报异常,如果使用stop(),子线程与后面的代码不会执行
thread.stop();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"end");
}
}
输出结果:(结果是子线程在stop后面的全部没有输出,连个异常都没抛,但是使用interrupt方法后面的代码可以继续执行)
mainstart
Thread-0start
mainend
三、非阻塞线程被interrupt
先上个例子
public class Test3 {
public static void main(String []args)
{
final Thread thread1= new Thread(new Runnable() {
public void run() {
while (true)
{
System.out.println(Thread.currentThread().getName()+"is running");
if(Thread.currentThread().isInterrupted())
{
System.out.println(Thread.currentThread().getName()+"interrupt,即将退出");
//throw new InterruptedException();
}
//Thread.sleep(1000);
//countDownLatch.countDown();
}
}
});
thread1.start();
new Thread(new Runnable() {
public void run() {
/* try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}*/
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
thread1.interrupt();
}
}).start();
}
}
输出结果:
Thread-0is running
Thread-0is running
Thread-0is running
Thread-0is running
Thread-0interrupt,即将退出
Thread-0is running
Thread-0interrupt,即将退出
Thread-0is running
Thread-0interrupt,即将退出
打印出来了即将推出字眼说明子线程已经被interrupt掉,但是我们发现子线程没有停止,那中断有个毛线用处,要他有何用?
表着急,线程中断仅仅是置线程的中断状态位,不会停止线程。需要用户自己去监视线程的状态为并做处理。支持线程中断的方法(也就是线程中断后会抛出interruptedException的方法)就是在监视线程的中断状态,一旦线程的中断状态被置为“中断状态”,就会抛出中断异常。
下面进行手动抛出异常
public class Test3 {
public static void main(String []args)
{
final Thread thread1= new Thread(new Runnable() {
public void run() {
try {
while (true)
{
System.out.println(Thread.currentThread().getName()+"is running");
if(Thread.currentThread().isInterrupted())
{
System.out.println(Thread.currentThread().getName()+"interrupt,即将退出");
throw new InterruptedException();
}
//countDownLatch.countDown();
}
} catch (InterruptedException e) {
System.out.println("进入ExceptionInterrupt2 类中run方法的catch了!");
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"is ending");
}
});
thread1.start();
new Thread(new Runnable() {
public void run() {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
thread1.interrupt();
}
}).start();
}
}
输出结果
Thread-0is running
Thread-0is running
Thread-0is running
Thread-0is running
Thread-0is running
Thread-0interrupt,即将退出
进入ExceptionInterrupt2 类中run方法的catch了!
java.lang.InterruptedException
at com.question.Test3$1.run(Test3.java:31)
at java.lang.Thread.run(Thread.java:748)
Thread-0is ending
这次程序就在我们捕捉到异常的位置停止了
四、阻塞线程被interrupt
下面再写一个阻塞子线程被interrupt的例子
public class Test3 {
public static void main(String []args)
{
final Thread thread1= new Thread(new Runnable() {
public void run() {
//for (int i=0;i<10;i++)
try {
while (true)
{
System.out.println(Thread.currentThread().getName()+"is running");
if(Thread.currentThread().isInterrupted())
{
System.out.println(Thread.currentThread().getName()+"interrupt,即将退出");
throw new InterruptedException();
}
Thread.sleep(1000);
}
} catch (InterruptedException e) {
System.out.println("进入ExceptionInterrupt2 类中run方法的catch了!");
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"is ending");
}
});
thread1.start();
new Thread(new Runnable() {
public void run() {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
//System.out.println("到达5个,结束线程");
thread1.interrupt();
//System.out.println("到达5个,结束线程");
}
}).start();
//service.shutdown();
}
}
输出结果:
Thread-0is running
进入ExceptionInterrupt2 类中run方法的catch了!
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at com.question.Test3$1.run(Test3.java:33)
at java.lang.Thread.run(Thread.java:748)
Thread-0is ending
阻塞线程会自动抛出异常,有点类似上面我们写的第二个例子,因为捕捉到了异常所以不会继续执行。
当一个线程处于中断状态时,如果再由wait、sleep以及jion三个方法引起的阻塞,那么JVM会将线程的中断标志重新设置为false,并抛出一个InterruptedException异常,然后开发人员可以中断状态位“的本质作用-----就是程序员根据try-catch功能块捕捉jvm抛出的InterruptedException异常来做各种处理,比如如何退出线程。总之interrupt的作用就是需要用户自己监视线程状态isinterrupted并进行处理。
五、总结
- stop与interrupt
- 非阻塞线程interrupt(手动抛异常)
- 阻塞线程interrupt