多线程中interrupt()详解以及如何结束线程
多线程中sleep(), wait()和interrupt()关系
对于理解interrupt(), 我们最重要的是要清楚interrupt()方法到底是什么作用, 在程序里面到底做了什么!!!
首先下结论:
my.interrupt()方法仅仅只是设置对my线程标记中断状态interrupt status.
提到interrupt()不得不补充一下阻塞, 当线程调用wait() , wait(long) ,或wait(long, int)的方法Object类,或join() , join(long) , join(long, int) , sleep(long) ,或sleep(long, int) 这个类的方法,线程会进入阻塞状态.
—如果A线程调用interrupt()标记中断状态, 当A线程进入阻塞状态时, 线程的interrupt status会被清除,并且将收到一个InterruptedException。
—如果该线程进入阻塞状态后, A线程不占用CPU, 无法调用interrupt()方法, 会抛出InterruptedException。
public class MyThread extends Thread {
@Override
public void run() {
try {
for (int i = 0; i < 10; i++) {
//阻塞1秒
sleep(1000);
for (int j = 0; j < 100; j++) {
System.out.println(System.currentTimeMillis()
+ Thread.currentThread().getName() + " " + j);
}
}
//阻塞期间catch异常,
} catch (InterruptedException e) {
System.out.println("支线程终止?");
}
//其实线程并没有真的停止,try catch外面的for循环会继续
for (int i = 0; i < 100; i++) {
System.out.println(i);
}
}
}
public class TestDemo01 {
public static void main(String[] args) throws InterruptedException {
MyThread my = new MyThread();
my.start();
//主线程1.1秒后,执行interrupt();
Thread.sleep(1100);
//interrupt()对my线程标记中断状态不影响正在运行的my线程.
my.interrupt();
System.out.println("主线程终止");
}
}
我们会发现, interrupt()并没有停止线程. interrupt()只是用来标记, 然后通过阻塞手段抛出异常, 跳出当前代码, 进入catch以及后续的代码, 达到类似中止线程的效果.
如下是反例, 没有阻塞和判断, interrupt()就没有任何意义, 代码如下,线程会完成整个循环:
public class MyThread extends Thread {
@Override
public void run() {
for (int i = 0; i < 1000000; i++) {
System.out.println(i);
}
}
}
public class TestDemo01 {
public static void main(String[] args) throws InterruptedException {
MyThread my = new MyThread();
my.start();
Thread.sleep(1100);
my.interrupt();
System.out.println("主线程终止");
}
}
consol:
999997
999998
999999
Process finished with exit code 0
那么, 我们到底如何结束线程呢?
上述代码中, 可以在run()中加入判断, 然后通过"return;" 结束线程
public void run() {
for (int i = 0; i < 1000000; i++) {
if(i==200){
return;
}
System.out.println(i);
}
}
public class TestDemo01 {
public static void main(String[] args) throws InterruptedException {
MyThread my = new MyThread();
my.start();
//Thread.sleep(1100);
//my.interrupt();
System.out.println("主线程终止");
}
}
console:
198
199
主线程终止?
Process finished with exit code 0
但是这样调用者就无法添加interrupt()控制线程.
那么如果没有阻塞, 还有没有其他办法中止线程呢?
Thread.currentThread().isInterrupted(): 测试线程是否已经中断,不会清除interrupt()标记;
通过这个方法判断中断标记, 如果有中断标记,返回true, 没有标记返回flase.
public class MyThread extends Thread {
@Override
public void run() {
try {
for (int i = 0; i < 1000000; i++) {
if(Thread.currentThread().isInterrupted()){
throw new InterruptedException();
}
System.out.println(i);
}
} catch (InterruptedException e) {
System.out.println("支线程终止");
}
}
}
public class TestDemo01 {
public static void main(String[] args) throws InterruptedException {
MyThread my = new MyThread();
my.start();
Thread.sleep(1100);
my.interrupt();
System.out.println("主线程终止");
}
}
consol:
197232
197233
197234
主线程终止?
Process finished with exit code 0