龙空技术网

java-2分钟学会如何正确优雅的关闭多线程

小瘦腿能劈大叉 187

前言:

现时兄弟们对“java线程的关闭”大体比较关心,咱们都想要学习一些“java线程的关闭”的相关文章。那么小编在网摘上搜集了一些对于“java线程的关闭””的相关知识,希望咱们能喜欢,你们快快来学习一下吧!

java创建多线程是基础中的基础,继承Thread类、实现Runnable接口和使用Callable和Future创建线程,或者使用线程池创建,这里就不阐述了,那么我们直接进入话题如何正确优雅的关系运行的线程呢?

在以往项目中,我经常看到一些人写的线程如下

public class ThreadDemo extends Thread { // 建立标记位 控制线程执行 private volatile boolean flag; public boolean isFlag() { return flag; } public void setFlag(boolean flag) { this.flag = flag; } //无参构造方法传入,或者给予一个默认值 ThreadDemo(boolean flag){ this.flag = flag; } @Override public void run() { while (flag) { System.out.println("标记执行线程 running..."); } }}//测试类class runDemo{ //isInterrupted() true如果这个线程已被中断; false否则。 //interrupt() 				中断这个线程 //interrupted() 测试当前线程是否中断,true如果当前线程已被中断; false否则。 public static void main(String[] args) throws InterruptedException { ThreadDemo threadDemo = new ThreadDemo(true); threadDemo.start(); threadDemo.setFlag(false); //查看这个方法是否被中断 System.out.println(threadDemo.isInterrupted());  //不出意外绝b false }}

这说明我jdk自带的方法判断竟然返回了flase,但是上这个方法也确实得到了中断,所以这种方法不推荐,真确的写法应该是这个样子的,去除标记位

public class ThreadDemo extends Thread { ThreadDemo(){ } @Override public void run() { while (!isInterrupted()) {//调用原生方法 System.out.println("标记执行线程 running..."); } }}//测试类class runDemo{ //isInterrupted() true如果这个线程已被中断; false否则。 //interrupt() 				中断这个线程 //interrupted() 测试当前线程是否中断,true如果当前线程已被中断; false否则。 public static void main(String[] args) throws InterruptedException { ThreadDemo threadDemo = new ThreadDemo(); threadDemo.start(); TimeUnit.SECONDS.sleep(2); //调用中断方法 threadDemo.interrupt(); //查看这个方法是否被中断 结果返回true,中断成功 System.out.println(threadDemo.isInterrupted()); }}

那么只是简单的这个样子是否认为就完整了呢?答案是不完整的,并且还有缺陷。大家如果仔细观察Thread api 会发现查用的join,sleep等等操作的线程api都会抛出异常java.lang.InterruptedException。下面我们就模拟一下,就是简单的 加了个睡眠,在睡眠过程中断

public class ThreadDemo extends Thread { ThreadDemo(){ } @Override public void run() { while (!isInterrupted()) { try { System.out.println("标记执行线程 running..."); //模拟睡眠中,我就执行中断 TimeUnit.SECONDS.sleep(200); } catch (InterruptedException e) { System.out.println("打印标记状态isInterrupted="+isInterrupted()); //打印标记状态isInterrupted=false e.printStackTrace(); } } }}//测试类class runDemo{ //isInterrupted() true如果这个线程已被中断; false否则。 //interrupt() 中断这个线程 //interrupted() 测试当前线程是否中断,true如果当前线程已被中断; false否则。 public static void main(String[] args) throws InterruptedException { ThreadDemo threadDemo = new ThreadDemo(); threadDemo.start(); TimeUnit.SECONDS.sleep(2); //调用中断方法 threadDemo.interrupt(); //查看这个方法是否被中断 System.out.println(threadDemo.isInterrupted()); }}

通过执行会发现抛出了异常 java.lang.InterruptedException: sleep interrupted。所以这个用例还是有问题,当外层调用了中断方法,里面的线程还在运行就会抛出异常并把标记位isInterrupted还原成flase,所以我们需要再次调用中断,合理的让他再次重置标记。改造最后步骤。

public class ThreadDemo extends Thread { ThreadDemo(){} @Override public void run() { while (!isInterrupted()) { try { //模拟睡眠中,我就执行中断 System.out.println("标记执行线程 running..."); TimeUnit.SECONDS.sleep(200); } catch (InterruptedException e) { System.out.println("打印标记状态isInterrupted="+isInterrupted()); interrupt(); System.out.println("打印标记状态isInterrupted="+isInterrupted()); if (!isInterrupted()) { e.printStackTrace(); } } } }}//测试类class runDemo{ //isInterrupted() true如果这个线程已被中断; false否则。 //interrupt() 中断这个线程 //interrupted() 测试当前线程是否中断,true如果当前线程已被中断; false否则。 public static void main(String[] args) throws InterruptedException { ThreadDemo threadDemo = new ThreadDemo(); threadDemo.start(); TimeUnit.SECONDS.sleep(2); //调用中断方法 threadDemo.interrupt(); //查看这个方法是否被中断 System.out.println(threadDemo.isInterrupted());//运行结果// 标记执行线程 running...// true 可以看到第一次调用interrupt() 然后咱们输出了一下isInterrupted 是true 但是在下面打印的时候又被重置了false// 打印标记状态isInterrupted=false// 打印标记状态isInterrupted=true }}

以上就是如何正确的使用线程并如何优雅的关闭线程,所以下次大家记得一定要用原生的方法,不要用布尔类型的值去做set和get操作。

小编自己创建的java交流群:705867428

目前刚创建的新交流群,我会帮助大家解答一些疑惑,如果有入门的小白不知道如何去学习我会告诉你我的学习路线,避免让大家少走一些坑。欢迎大家来交流,并且时长分享一些资料。资料大小一个4个TB哦,从小白基础到架构师大牛。欢迎加入

标签: #java线程的关闭