有关线程停止的常用方法有这3个:
Thread thread = new Thread(new Test());
void thread.interrupt();
boolean thread.isInterrupted();
static boolean Thread.interrupted() or thread.interrupted()
第一个方法是将thread对象所在的线程停止状态标示为true(true代表停止该线程)
第二个方法是判断thread对象所在的线程是否停止
第三个方法是个静态方法判断当前线程中断状态,怎么理解当前线程呢,意思是不管当前方法是哪个对象调用,它都不管,只作用在当前运行的线程上,如上面的代码如果在main方法中那么Thread.interrupted() or thread.interrupted()都是判断的是main线程是否终止 ,并且还会将标记重新设置为false,这也是唯一一个能清除线程状态的方法
网上还包括有些书本上,用volatile设置boolean变量来中断线程,虽然在某些情况下是正确的,但其实是错误的,因为如果线程被阻塞了,就算volatile被改为ture了,但是程序一直阻塞在哪里,程序依然不会停止,这种情况我会在后面说出做出说明。
上面几个方法并不像被jdk弃用的stop()方法停止线程那样干脆,调用了就停止。而是将停止线程的权利交给了线程对象本身,这样做避免了如果当前线程还有事情没有做完,如果就给它了停止了,会出现一系列不可想象的后果,特别在涉及商用,银行等方面。
而使用interrupt来停止线程还有一个重大好处就是,即使线程处于阻塞状态,被通知线程依然能够响应中断。也就是说依然可以停止。
话说怎么多 来看看具体例子:
public class Test implements Runnable {
public static void main(String[] args) throws InterruptedException{
Thread thread = new Thread(new Test());
thread.start();
Thread.sleep(500);
thread.interrupt();
}
@Override
public void run() {
// TODO Auto-generated method stub
try {
while(!Thread.currentThread().isInterrupted()) {
Thread.sleep(100000000); //模拟一个阻塞方法
} }catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
上述结果可知,因为sleep方法是个阻塞方法 ,当我们还在执行 Thread.sleep(100000000);;这行代码时, thread.interrupt();就开始通知此线程可以中断了,虽然这个线程还在休息中,但他还是被唤醒了,最终抛出一个异常,在sleep中被interrupted,最后程序还是停止了,这样就很好吧。
再看volatile 关键字情况
public class Test implements Runnable {
private volatile static boolean flag = true;
public static void main(String[] args) throws InterruptedException{
Thread thread = new Thread(new Test());
thread.start();
Thread.sleep(500);
Test.flag = false;
//thread.interrupt();
}
@Override
public void run() {
// TODO Auto-generated method stub
try {
while(flag) {
Thread.sleep(100000000); //模拟一个阻塞方法
} }catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
运行结果:可以看到程序一直在运行中,虽然我将Test.flag = false;依然没用。
最后还有个有趣的问题 try catch 位置不一样 也会影响结果 ,还是之前的代码:
public class Test implements Runnable {
public static void main(String[] args) throws InterruptedException{
Thread thread = new Thread(new Test());
thread.start();
Thread.sleep(500);
System.out.println("main休眠结束");
thread.interrupt();
}
@Override
public void run() {
// TODO Auto-generated method stub
while(!Thread.currentThread().isInterrupted()) {
try {
System.out.println("---");
Thread.sleep(2000);
}catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
结果:
我们将try catch 放在循环里面,抛出异常后继续打印,没有停止。
这就隐射出一种编程规法,将如你两个程序员一起编写一个项目,a程序员是编写run方法的,b程序员是写编写run方法里面调用的方法,假如a程序想要想停止这个线程,但是发现我怎么都停止不了,结果是b程序在自己写的方法里进行了try catch ,没有抛出来,这在实际项目中很难排查,所以这就是为什么异常要向上抛,抛到顶层来处理。如果你实在要处理也是有办法的。。看如下代码
public class Test implements Runnable {
public static void main(String[] args) throws InterruptedException{
Thread thread = new Thread(new Test());
thread.start();
Thread.sleep(1000);
System.out.println("main休眠结束");
//Test.flag = false;
thread.interrupt();
}
@Override
public void run() {
// TODO Auto-generated method stub
while(!Thread.currentThread().isInterrupted()) {
a();
}
}
public static void a() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
Thread.currentThread().interrupt();
e.printStackTrace();
}
}
}
如果对你有帮助,还请点个赞