前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >java 线程interupt stop(dep)[通俗易懂]

java 线程interupt stop(dep)[通俗易懂]

作者头像
全栈程序员站长
发布2022-11-01 15:35:44
5580
发布2022-11-01 15:35:44
举报
文章被收录于专栏:全栈程序员必看

大家好,又见面了,我是你们的朋友全栈君

java 线程interupt stop(dep)

https://blog.csdn.net/zbw18297786698/article/details/53432879/

1、Java中API自带的stop()方法,来终止线程

查阅JDK,不难发现Thread提供了一个stop()方法,但是stop()方法是一个被废弃的方法。为什么stop()方法被废弃而不被使用呢?原因是stop()方法太过于暴力,会强行把执行一半的线程终止。这样会就不会保证线程的资源正确释放,通常是没有给与线程完成资源释放工作的机会,因此会导致程序工作在不确定的状态下。关于使用stop()方法,造成数据不同步的例子如下。

下面代码模拟一个过程,读线程ReadObjectThread在读到对象的ID和Name不一致时,会输出这些对象;而写线程ChangeObjectThread总是写入连个相同的数值。但是在代码中因为使用了stop()强行停止线程,造成了数据的不同步。

public class ThreadStopUnSafe { public static User user = new User(); // 改变user变量的线程 public static class ChangeObjectThread extends Thread { @Override public void run() { while (true) { synchronized (ThreadStopUnSafe.class) { int v = (int) (System.currentTimeMillis() / 1000); user.setId(v); // to do sth try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } user.setName(String.valueOf(v)); } // 让出CPU,给其他线程执行 Thread.yield(); } } } // 读取user变量的线程 public static class ReadObjectThread extends Thread { @Override public void run() { while (true) { synchronized (ThreadStopUnSafe.class) { if (user.getId() != Integer.parseInt(user.getName())) { System.out.println(user.toString()); } } // 让出CPU,给其他线程执行 Thread.yield(); } } } // 测试 public static void main(String[] args) throws InterruptedException { new ReadObjectThread().start(); while (true) { Thread t = new ChangeObjectThread(); t.start(); Thread.sleep(150); //使用stop()方法,强制停止线程 t.stop(); } } }

User.java的代码

public class User { private int id; private String name; public User() { this(0, “0”); } public User(int id, String name) { this.id = id; this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return “User [id=” + id + “, name=” + name + “]”; } }

程序的运行结果,出现了数据不一致的情况。

User [id=1480649515, name=1480649514] User [id=1480649516, name=1480649515]

2、使用boolean类型的变量,来终止线程

那么如果需要停止一个线程时,应该怎么办?其实方法很简单,只是需要我们执行确定线程什么时候退出就可以了。仍用本例来说,只需要在ChangeObjectThread线程中增加一个stopMe()方法就可以了。

public static class ChangeObjectThread extends Thread { // 用于停止线程 private boolean stopMe = true; public void stopMe() { stopMe = false; } @Override public void run() { while (stopMe) { synchronized (ThreadStopSafeBoolean.class) { int v = (int) (System.currentTimeMillis() / 1000); user.setId(v); // to do sth try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } user.setName(String.valueOf(v)); } // 让出CPU,给其他线程执行 Thread.yield(); } } }

在上面的代码里面,定义了一个标记变量stopMe,用于指示线程是否需要退出。当stopMe()方法被调用时,stopme就会被赋值为false,此时在代码里面的while(stopMe)就会检测到这个改动,线程就退出了。

3、java线程的中断

中断可以理解为线程的一个标识位属性,它表示一个运行中的线程是否被其他线程进行了中断操作。中断好比其他线程对该线程打了个招呼,其他线程通过调用该线程的interrupt()方法对其进行中断操作。

线程通过检查自身是否被中断来进行响应,线程通过方法isInterrupted()来进行判断是否被中断,也可以调用静态方法Thread.interrupted()对当前线程的中断标识位进行复位。如果该线程已经处于终结状态,即使该线程被中断过,在调用该线程对象的isInterrupted()时依旧会返回false。

从Java的API中可以看到,许多声明抛出InterruptedException的方法(例如Thread.sleep(longmillis)方法,当线程在sleep()休眠时,如果被中断,这个异常就会产生)。这些方法在抛出InterruptedException之前,Java虚拟机会先将该线程的中断标识位清除,然后抛出InterruptedException,此时调用isInterrupted()方法将会返回false。

在代码清单4-7所示的例子中,首先创建了两个线程,SleepThread和BusyThread,前者不停地睡眠,后者一直运行,然后对这两个线程分别进行中断操作,观察二者的中断标识位。

import java.util.concurrent.TimeUnit; public class Interrupted { public static void main(String[] args) throws Exception { // sleepThread不停的尝试睡眠 Thread sleepThread = new Thread(new SleepRunner(), “SleepThread”); sleepThread.setDaemon(true); // busyThread不停的运行 Thread busyThread = new Thread(new BusyRunner(), “BusyThread”); busyThread.setDaemon(true); sleepThread.start(); busyThread.start(); // 休眠5秒,让sleepThread和busyThread充分运行 TimeUnit.SECONDS.sleep(2); sleepThread.interrupt(); busyThread.interrupt(); System.out.println(“SleepThread interrupted is “ + sleepThread.isInterrupted()); System.out.println(“BusyThread interrupted is “ + busyThread.isInterrupted()); // 防止sleepThread和busyThread立刻退出 TimeUnit.SECONDS.sleep(2); } static class SleepRunner implements Runnable { @Override public void run() { while (true) { try { TimeUnit.SECONDS.sleep(10); } catch (InterruptedException e) { //e.printStackTrace(); } } } } static class BusyRunner implements Runnable { @Override public void run() { while (true) { } } } }

程序的运行结果

SleepThread interrupted is false BusyThread interrupted is true

从结果可以看出,抛出InterruptedException的线程SleepThread,其中断标识位被清除了,而一直忙碌运作的线程BusyThread,中断标识位没有被清除。

4、使用中断来终止线程

下面的例子代码,使用了中断机制来终止一个线程。

package com.baowei.threadinter; public class ThreadStopSafeInterrupted { public static void main(String[] args) throws InterruptedException { Thread thread = new Thread() { @Override public void run() { while (true) { // 使用中断机制,来终止线程 if (Thread.currentThread().isInterrupted()) { System.out.println(“Interrupted …”); break; } try { Thread.sleep(3000); } catch (InterruptedException e) { System.out.println(“Interrupted When Sleep …”); // Thread.sleep()方法由于中断抛出异常。 // Java虚拟机会先将该线程的中断标识位清除,然后抛出InterruptedException, // 因为在发生InterruptedException异常的时候,会清除中断标记 // 如果不加处理,那么下一次循环开始的时候,就无法捕获这个异常。 // 故在异常处理中,再次设置中断标记位 Thread.currentThread().interrupt(); } } } }; // 开启线程 thread.start(); Thread.sleep(2000); thread.interrupt(); } }

程序的运行结果

Interrupted When Sleep … Interrupted …

5、关于终止线程的选择

感觉使用boolean类型的变量,实现起来比较简单。还不会引起数据的不正确问题。

6、参考的书籍

Java高并发程序设计

Java并发编程的艺术

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/206855.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022年10月24日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • java 线程interupt stop(dep)
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档