Java中线程中断的几种方法小结
使用线程的stop()来中断线程
这种方式是直接调用线程的stop()方法,可以直接让线程终止运行,是一种很暴力的方式。
public static void test02(){ Thread thread1 = new Thread(()->{ System.out.println("thread1启动了"); while (true){ System.out.println("thread1循环中..."); } }); thread1.start(); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("准备关闭thread1线程"); thread1.stop(); System.out.println("主线程停止"); }
运行结果如下
使用线程的interrupt()来中断线程
public static void testInterrupt(){ Thread thread1 = new Thread(() -> { while (true){ boolean interrupted = Thread.currentThread().isInterrupted(); if(interrupted){ System.out.println("thread1线程被中断"); break; } System.out.println("thread1循环中..."); } }); thread1.start(); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } thread1.interrupt(); }
运行结果如下
interrupt相比于stop中断线程的方式更加温柔,当主线程调用thread1线程的interrupt方法其实本质就是将thread1线程的中断标志设置为true,仅此而已。被设置中断标志的线程还是可以继续运行的,不受影响,也就是如果thread不主动结束线程该线程是不会停止的。
代码演示如下
public static void testInterrupt2(){ Thread thread1 = new Thread(() -> { while (true){ boolean interrupted = Thread.currentThread().isInterrupted(); System.out.println("当前中断标志位状态为:"+interrupted); System.out.println("thread1循环中..."); } }); thread1.start(); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } thread1.interrupt(); }
运行结果如下
当调用了thread1.interrupt();之后thread1还会一直无限执行下去。
如果thread1线程处于被阻塞状态(例如处于sleep,wait,join等状态),在别的线程调用thread1的interrupt方法,那么线程的中断状态会被清除,并抛出InterruptedException异常
代码如下
public static void testInterrupt3(){ Thread thread1 = new Thread(() -> { System.out.println("thread1线程启动了。。。"); try { Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } }); thread1.start(); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } thread1.interrupt(); }
运行结果如下
1.线程启动是,默认中断标志位为false
2.如果main线程调用了thread1的interrupt()方法,中断标志位就变成了true
3.正常情况,中断标志位为true,如果thread1判断中断标志位为true就中断执行,则thread1停止,如果thread1线程自己不终止运行则不会停止。
4.异常情况,如果thread1线程正处于阻塞状态(例如处于sleep,wait,join等状态),将会把中断状态清除,并且将抛出InterruptedException异常,此时中断标志位还是false,thread1线程还会继续执行。
测试异常情况,并且循环不停止的情况,代码如下
public static void testInterrupt4(){ Thread thread1 = new Thread(() -> { System.out.println("thread1线程启动了。。。"); try { Thread.sleep(5000); } catch (Exception e) { e.printStackTrace(); } while (true){ boolean interrupted = Thread.currentThread().isInterrupted(); if(interrupted){ System.out.println("thread1程序终止"); break; } } }); thread1.start(); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } thread1.interrupt(); }
程序并没有停止
5.解决异常情况的方法,就是在catch块中,需要再次将中断标志位设置为true,2次调用才能使中断标志位改为true
public static void testInterrupt5(){ Thread thread1 = new Thread(() -> { System.out.println("thread1线程启动了。。。"); try { Thread.sleep(5000); } catch (Exception e) { // 抛出异常过后在此调用interrupt方法 Thread.currentThread().interrupt(); e.printStackTrace(); } while (true){ boolean interrupted = Thread.currentThread().isInterrupted(); if(interrupted){ System.out.println("thread1程序终止"); break; } } }); thread1.start(); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } thread1.interrupt(); }
关于Thread.interrupted()方法
判断线程是否被中断并清除当前中断状态
这个方法做了两件事情
1.返回当前线程的中断状态
2.将当前线程的中断状态清零并重新设置为false,清除线程的中断状态
public static void testInterrupt6(){ System.out.println(Thread.currentThread().getName() + "\t" + Thread.interrupted()); System.out.println(Thread.currentThread().getName() + "\t" + Thread.interrupted()); System.out.println("1111111111111111"); // 中断标志位设置为true Thread.currentThread().interrupt(); System.out.println("2222222222222222"); System.out.println(Thread.currentThread().getName() + "\t" + Thread.interrupted()); System.out.println(Thread.currentThread().getName() + "\t" + Thread.interrupted()); }
关于isInterrupted()方法
该方法只会返回当前线程的中断标志位的状态;不会清除当前线程的中断标志位的状态
public static void testInterrupt7(){ System.out.println(Thread.currentThread().getName() + "\t" + Thread.currentThread().isInterrupted()); System.out.println(Thread.currentThread().getName() + "\t" + Thread.currentThread().isInterrupted()); System.out.println("1111111111111111"); // 中断标志位设置为true Thread.currentThread().interrupt(); System.out.println("2222222222222222"); System.out.println(Thread.currentThread().getName() + "\t" + Thread.currentThread().isInterrupted()); System.out.println(Thread.currentThread().getName() + "\t" + Thread.currentThread().isInterrupted()); }
关于Thread的静态方法interrupted和Thread实例方法isInterrupted底层源码
1.interrupted
public static boolean interrupted() { return currentThread().isInterrupted(true); }
2.isInterrupted
public boolean isInterrupted() { return isInterrupted(false); }
本质上都是调用了实例的isInterrupted方法,只是传入的参数有所不同,当传入true时,会情空当前线程的中断标志,重置为false,方传入false时,不会清空。
private native boolean isInterrupted(boolean ClearInterrupted);
该方法是被native修饰的方法
总结
- public void interrupt() 其中interrupt()是一个实例方法
它通知目标线程中断,也仅仅是设置目标线程的中断标志位为true. - public boolean isInterrupted() 其中isInterrupted()方法也是一个实例方法
它判断当前线程是否被中断(通过检查中断标志位)并获得中断标志 - public static boolean interrupted() . 该方法是Thread类的静态方法
返回当前线程的中断状态真实值后会将当前线程的中断状态设置为false,此方法调用之后会清除当前线程的中断标志位的状态。
通过共享变量来控制
1.使用volatile 关键字来实现线程中断
static volatile boolean run = true; public static void main(String[] args) { new Thread(()->{ while (run){ System.out.println("线程1执行中..."); } }).start(); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } run = false; System.out.println("主线程结束"); }
2.使用同步代码块synchronized来实现线程中断
static boolean run = true; static Object object = new Object(); public static void main(String[] args) { new Thread(()->{ while (run){ System.out.println("线程1执行中..."); synchronized (object){ } } }).start(); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } run = false; System.out.println("主线程结束"); }
3.使用AtomicBoolean 来实现线程中断
public static void main(String[] args) { AtomicBoolean run = new AtomicBoolean(true); new Thread(()->{ while (run.get()){ System.out.println("线程1执行中..."); } }).start(); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } run.set(false); System.out.println("主线程结束"); }
其运行结果如下
到此这篇关于Java中线程中断的几种方法小结的文章就介绍到这了,更多相关Java 线程中断内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
postman中参数和x-www-form-urlencoded传值的区别及说明
在Postman中,参数传递有多种方式,其中params和x-www-form-urlencoded最为常用,Params主要用于URL中传递查询参数,适合GET请求和非敏感数据,其特点是将参数作为查询字符串附加在URL末尾,适用于过滤和排序等操作2024-09-09解决Spring配置文件中bean的property属性中的name出错问题
这篇文章主要介绍了解决Spring配置文件中bean的property属性中的name出错问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教2021-07-07elasticsearch的zenDiscovery和master选举机制原理分析
这篇文章主要介绍了elasticsearch的zenDiscovery和master选举机制原理分析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪2022-04-04
最新评论