上篇说到public final void stop()函数已过时,那怎么才能优雅的停止线程呢?
在java中又一下三种方式可以停止正在运行的线程
- 使用退出标志,使线程正常退出,也就是当润运行完成后线程终止
- 使用stop()强制结束 ,这个已经说过已经过时就不再详细说明了
- 使用interrupt方法中断线程
设置标志位,结束线程
public class FirstThreadTest extends Thread {
public boolean flag=true;
@Override
public void run() {
while (flag){
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("运行中。。。" );
};
System.out.println("线程即将结束" );
}
public static void main(String[] args) {
FirstThreadTest thread=new FirstThreadTest();
thread.start();//启动线程 线程处于准备运行阶段
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
thread.flag=false;
}
}
运行结果:
运行中。。。
运行中。。。
线程即将结束
Process finished with exit code 0
从结果可以看出是停止了,但是这种方式还是问题,看下面代码
public class FirstThreadTest extends Thread {
public boolean flag=true;
@Override
public void run() {
while (flag){
};
System.out.println("线程即将结束" );
}
public static void main(String[] args) {
FirstThreadTest thread=new FirstThreadTest();
thread.start();//启动线程 线程处于准备运行阶段
System.out.println("线程状态1"+ thread.isAlive());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
thread.flag=false;
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程状态2"+ thread.isAlive());
}
}
运行结果:
线程状态1true
线程状态2true
可以看出线程并没有停止,两次线程状态都是活跃中,并且 “线程即将结束” 没有打印,说明还在循环中,这是为什么呢
造成这种问题的原因是 线程私有栈,与公共栈中的值不同步造成的,解决的方法就是在使用volatile关键字
示例
public class FirstThreadTest extends Thread {
public volatile boolean flag=true;
@Override
public void run() {
while (flag){
};
System.out.println("线程即将结束" );
}
public static void main(String[] args) {
FirstThreadTest thread=new FirstThreadTest();
thread.start();//启动线程 线程处于准备运行阶段
System.out.println("线程状态1"+ thread.isAlive());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
thread.flag=false;
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程状态2"+ thread.isAlive());
}
}
运行结果
线程状态1true
线程即将结束
线程状态2false
Process finished with exit code 0
可以看出现在线程安全停止了
interrupt 中断线程
相关函数
- public void interrupt()
中断这个线程。
除非当前线程中断自身,这是始终允许的,所以调用此线程的checkAccess方法,这可能会导致抛出SecurityException 。
如果该线程阻塞的调用wait() , wait(long) ,或wait(long, int)的方法Object类,或者在join() , join(long) , join(long, int) , sleep(long) ,或sleep(long, int) ,这个类的方法,那么它的中断状态将被清除,并且将收到一个InterruptedException 。 - public static boolean interrupted()
测试当前线程是否中断。 该方法可以清除线程的中断状态 。 换句话说,如果这个方法被连续调用两次,那么第二个调用将返回false(除非当前线程再次中断,在第一个调用已经清除其中断状态之后,在第二个调用之前已经检查过)。
忽略线程中断,因为线程在中断时不存在将被该方法返回false所反映
true如果这个线程已被中断; false否则。 - public boolean isInterrupted()
测试这个线程是否被中断。 线程的中断状态不受此方法的影响。
忽略线程中断,因为线程在中断时不存在将被该方法返回false所反映。
true如果这个线程已被中断; false否则。
使用示例
public class FirstThreadTest extends Thread {
@Override
public void run() {
while (true){
if (isInterrupted()){
break;
}
}
System.out.println("线程即将结束");
}
public static void main(String[] args) {
FirstThreadTest thread=new FirstThreadTest();
thread.start();//启动线程 线程处于准备运行阶段
System.out.println("线程状态1"+ thread.isAlive());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
thread.interrupt();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程状态2"+ thread.isAlive());
}
}
运行结果
线程状态1true
线程即将结束
线程状态2false
Process finished with exit code 0
该方法还有一个问题,从interrupt说明中可以看出 当线程调用wait join sleep阻塞这时会抛售一个异常InterruptedException
那么我们可以捕获这个异常退出该线程
public class FirstThreadTest extends Thread {
@Override
public void run() {
while (true){
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("线程即将结束");
}
if (isInterrupted()){
break;
}
}
System.out.println("线程即将结束");
}
public static void main(String[] args) {
FirstThreadTest thread=new FirstThreadTest();
thread.start();//启动线程 线程处于准备运行阶段
System.out.println("线程状态1"+ thread.isAlive());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
thread.interrupt();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程状态2"+ thread.isAlive());
}
}
运行结果1:
线程状态1true
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at com.jelly.threadtest1.FirstThreadTest.run(FirstThreadTest.java:12)
线程即将结束
线程状态2true
运行结果2:
线程状态1true
线程即将结束
线程状态2true
注意:只有线程进入sleep wait join状态时调用interrupt才会抛出该异常,如果当前线程有调用阻塞,但是现在没有在该状态下则不会抛出异常
如上面例子:不一定每次都会抛出该异常