8.优雅地停止线程
优雅地停止线程
导言
如何让正在运行的线程优雅的停下来,这个问题一直是面试必考题。下面将介绍一种让线程优雅的停下来的方法,这就是位于thread类里面的interrupt方法,
它的作用就是中段线程。
接下来我们将从两个方面演示该方法。
第一个方面就是停止正在运行的线程。
第二个方面就是停止休眠中的线程。
停止正在运行的线程
首先来看第一个方面,我们先定义一个任务,任务的内容,就是无限输出正在运行这句话。
package com.chenjie.executor.day08; /** * 自定义task */ public class Task implements Runnable { @Override public void run() { while (true) { System.out.println("正在执行"); } } }
接下来我们将任务创建出来,然后创建线程并将任务传递给线程,接着启动线程,为了让中断效果更明显,在中段线程前,就用sleep方法使主线程休眠一秒钟,最后就用interrupt方法中断线程。
package com.chenjie.executor.day08; public class Main1 { public static void main(String[] args) { Task task=new Task(); Thread thread = new Thread(task); thread.start(); try { thread.sleep(1000L); } catch (InterruptedException e) { e.printStackTrace(); } thread.interrupt(); } }
从运行结果来看,好像出了点问题,线程没有停下来,程序也没有结束,这是怎么回事?
原因就在于 interrupt方法仅仅只是将线程标记为中断状态,
他没有实际去停止这个线程,如果想要线程停下来,则需要我们手动去判断线程是否被中断,然后对此作出反应
判断线程是否被中断,有两个方法,分别是 isinterrupted和interrupt的。
Is interrupt的是一个非静态方法,它的作用是判断线程是否被中断。
Interrupt的是一个静态方法,它可以直接被thread的类名调用,作用也是判断线程是否被中断,并且它可以清除中断标记,这也是它和interrupt的方法的区别。
下面来看看这两个方法分别如何如何使用。首先是isinterrupt的。他返回一个布尔类型,线程被中段返回true,否则返回false。
改写之前的任务,首先调用currentthread方法获取当前正在执行任务的线程,然后调用该线程的isinterrupt,判断线程是否被中断。当线程被中断时,结束循环,此时线程就停下来了。
package com.chenjie.executor.day08; /** * 自定义task */ public class Task implements Runnable { @Override public void run() { while (true) { Thread thread = Thread.currentThread(); if(thread.isInterrupted()){ break; }; System.out.println("正在执行"); } } }
下面来看一下运行结果。从运行结果来看,程序经过一秒钟后运行结束,说明线程的确被中断了。
下面再来看看interrupt的方法,它返回的也是一个Boolean类型,线程被中断返回true,否则返回false。
改写之前的任务,这里直接使用所谓的类名调用interrupt的方法,判断线程是否被中断,当线程被中断时结束循环。
package com.chenjie.executor.day08; /** * 自定义task */ public class Task1 implements Runnable { @Override public void run() { while (true) { if(Thread.interrupted()){ break; }; System.out.println("正在执行"); } } }
下面来看一下运行结果。从运行结果来看,程序也是经过一秒钟后结束,说明线程也的确被中断了。
package com.chenjie.executor.day08; public class Main1 { public static void main(String[] args) { // Task task=new Task(); // Thread thread = new Thread(task); // thread.start(); // try { // thread.sleep(1000L); // } catch (InterruptedException e) { // e.printStackTrace();a // } // thread.interrupt(); Task1 task=new Task1(); Thread thread = new Thread(task); thread.start(); try { thread.sleep(1000L); } catch (InterruptedException e) { e.printStackTrace(); } thread.interrupt(); } }
线程中断
接下来我们来看看线程中断的标记是怎样的。首先来看isInterrupted的方法的输出结果。从结果来看,线程一开始它没有被中断,输出的结果是false,一秒钟后线程被中断,输出的结果变为了true。
package com.chenjie.executor.day08; /** * 自定义task */ public class Task2 implements Runnable { @Override public void run() { while (true) { Thread thread = Thread.currentThread(); System.out.println(thread.isInterrupted()); } } }
false false false true true true
我们再来看看interrupted的方法,从结果来看,它的结果和之前的结果有点不同,线程一开始没有被中断,输出的结果为false,一秒钟后线程被中断,结果变true了。然后线程中段标记被清除,输出的结果又变为了false。
false false false true true true false false false
停止休眠中的线程
好的,第一个方面,演示完毕。我们再来看看第二种方面,停止休眠中的线程,还是自定义一个任务,然后调用sleep方法,使当前线程休眠10秒钟,使用try catch捕获thread方法抛出的异常。
package com.chenjie.executor.day08; public class Main1 { public static void main(String[] args) { // Task2 task=new Task2(); // Thread thread = new Thread(task); // thread.start(); // try { // thread.sleep(1000L); // } catch (InterruptedException e) { // e.printStackTrace(); // } // thread.interrupt(); // Task3 task = new Task3(); // Thread thread = new Thread(task); // thread.start(); // try { // thread.sleep(1000L); // } catch (InterruptedException e) { // e.printStackTrace(); // } // thread.interrupt(); Task4 task = new Task4(); Thread thread = new Thread(task); thread.start(); try { thread.sleep(1000L); } catch (InterruptedException e) { e.printStackTrace(); } thread.interrupt(); } }
package com.chenjie.executor.day08; /** * 自定义task */ public class Task4 implements Runnable { @Override public void run() { try { Thread.sleep(10000L); } catch (InterruptedException e) { e.printStackTrace(); } } }
下面来看看运行结果怎么样。从运行结果来看,程序发生了异常,该异常是中断休眠中的线程引发的,叫做中段线程异常。
总结
最后我们来总结一下本节内容,本节介绍了thread里面三个方法,第一个是interrupt方法,它是一个非静态方法,作用是中断线程。
第二个是isinterrupted的方法,它也是一个非静态方法,作用是判断线程是否被中断。
第三个是interrupted方法,它是一个静态方法,直接通过所谓的类名调用,作业是判断线程是否被中断,并清除中断标记,在实际开发中偶尔也会用到它们。
本文来自博客园,作者:小陈子博客,转载请注明原文链接:https://www.cnblogs.com/cj8357475/p/16085986.html