中断线程
在学习Java要注意到,Java更多的是应用在系统当中,系统如果收发一个很大的文件的话,很容易让人对这个事情感到厌烦,所以在使用线程的时候经常要考虑到存在需要给信号进行中断,Java可以很简单的出来处理这个情况,即使用interuped()办法进行标记,当线程存在处于interruted的状态下,就需要立刻暂停。
说的太多没有意义,可以直接看例子
public class Main {
public static void main(String[] args) throws InterruptedException {
Thread t = new MyThread();
t.start();
Thread.sleep(1); // 暂停1毫秒
t.interrupt(); // 中断t线程
t.join(); // 等待t线程结束
System.out.println("end");
}
}
class MyThread extends Thread {
public void run() {
int n = 0;
while (! isInterrupted()) {
n ++;
System.out.println(n + " hello!");
}
}
}
在这个例子当中在调用了了interupt()和join()两个办法,可以说是很好的例子
‘但假设我现在做了另一个大胆的尝试,假如我做了另一个尝试,即我将interrupt和join两个函数给直接注释掉,那么会发生什么事情,
和大家想象中的一样,会持续的往输出,而且在外界干预之前不会暂停,那么应该存在更好的办法面对这种情况,因为这实在是太过于极端,所幸,确实存在这样的方法(虽然存在一些麻烦)
public class Main {
public static void main(String[] args) throws InterruptedException {
Thread t = new MyThread();
t.start();
Thread.sleep(1000);
t.interrupt(); // 中断t线程
t.join(); // 等待t线程结束
System.out.println("end");
}
}
class MyThread extends Thread {
public void run() {
Thread hello = new HelloThread();
hello.start(); // 启动hello线程
try {
hello.join(); // 等待hello线程结束
} catch (InterruptedException e) {
System.out.println("interrupted!");
}
hello.interrupt();
}
}
class HelloThread extends Thread {
public void run() {
int n = 0;
while (!isInterrupted()) {
n++;
System.out.println(n + " hello!");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
break;
}
}
}
}
main
线程通过调用t.interrupt()
从而通知t
线程中断,而此时t
线程正位于hello.join()
的等待中,此方法会立刻结束等待并抛出InterruptedException
。由于我们在t
线程中捕获了InterruptedException
,因此,就可以准备结束该线程。在t
线程结束前,对hello
线程也进行了interrupt()
调用通知其中断。如果去掉这一行代码,可以发现hello
线程仍然会继续运行,且JVM不会退出
boolean running
是一个线程间共享的变量。线程间共享变量需要使用volatile
关键字标记,确保每个线程都能读取到更新后的变量值。
对目标线程调用interrupt()
方法可以请求中断一个线程,目标线程通过检测isInterrupted()
标志获取自身是否已中断。如果目标线程处于等待状态,该线程会捕获到InterruptedException
;
目标线程检测到isInterrupted()
为true
或者捕获了InterruptedException
都应该立刻结束自身线程;
通过标志位判断需要正确使用volatile
关键字;
volatile
关键字解决了共享变量在线程间的可见性问题。