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

java 线程interupt stop(dep)[通俗易懂] java线程interuptstop(dep) https://blog.csdn.net/zbw18297786698/article/details/53432879/1、Java中API自带的stop()方法,来终止线程       查阅JDK,不难发现Thread提供了一个stop()方法,但是stop()方法是一个被废弃的方法。为什么sto…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全家桶1年46,售后保障稳定

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并发编程的艺术

posted on 2018-10-22 14:33 CreatorKou 阅读() 评论() 编辑 收藏

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

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

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • sql:常用:group by 多个字段「建议收藏」

    sql:常用:group by 多个字段「建议收藏」首先groupby的简单说明:  groupby一般和聚合函数一起使用才有意义,比如countsumavg等,使用groupby的两个要素:  (1)出现在select后面的字段要么是是聚合函数中的,要么就是groupby中的.  (2)要筛选结果可以先使用where再用groupby或者先用groupby再用having下面看下groupb…

    2022年5月25日
    75
  • 表复制:SELECT INTO 和 INSERT INTO SELECT

    表复制:SELECT INTO 和 INSERT INTO SELECTINSERTINTOSELECT语句语句形式为:InsertintoTable2(field1,field2,…)selectvalue1,value2,…fromTable1要求目标表Table2必须存在,由于目标表Table2已经存在,所以我们除了插入源表Table1的字段外,还可以插入常量注意(1)要求目标表Tabl

    2022年7月16日
    13
  • 史上最详细Git使用教程[通俗易懂]

    史上最详细Git使用教程[通俗易懂]本篇为廖雪峰老师官方网站中Git教程的学习笔记Git是世界上最先进的分布式版本控制系统,克隆一个项目的速度非常快每个开发都可以从master上克隆一个本地版本库,就算没有网络,也可以提交代码到本地仓库、查看log、创建项目分支等等每个版本库都可以创建无限个分支,分支是个完整的目录,且这个目录拥有完整的实际文件一、安装网上搜一下安装教程,这里就不介绍了安装完成后,在开始菜单里…

    2022年4月30日
    74
  • 卡盟货源对接_卡盟排行

    卡盟货源对接_卡盟排行最近,很多小伙伴们都在想搭建一个卡盟的主站,但是鉴于很多人都不太懂编程,也不知道如何找到源码。所以现在小编就为大家带来搭建卡盟主站教程,而且还把源码也一起送来了,想要搭建卡盟主站的话就记得一定要下载哦!搭建卡盟主站教程介绍1,完整无误经过校验的卡盟平台源码2,基于Ecshop内核的卡盟平台,游戏点卡销售的首选平台PHP+MYSQL3,前台模板已做深层SEO优化便于搜索引擎收录寻找卡盟源码1网…

    2022年8月12日
    3
  • pycharm卸载再安装_pycharm双击无法打开

    pycharm卸载再安装_pycharm双击无法打开今个发现原来下载的2017版的pycharm过期了,用一会就闪退,emmm。就想下一个新的进行迭代,结果安装好并重启了,软件就是打不开…方法一1.打开C:\Windows\System32;以管理员身份运行cmd.exe;2.在打开的cmd窗口中,输入netshwinsockreset,按回车键;3.重启电脑;博主使用这个方法后,双击后还是不行。随即用了方法二,如下:方法二只需要打开C:\Users\admin后面的admin换成你自己的当前用户名(如下图),然后把所

    2022年8月29日
    1
  • cas 原理分析

    cas 原理分析CAS原理分析1、了解java中锁的类型1.1悲观锁(PessimisticLock)顾名思义,就是很悲观,假定会发生并发冲突,屏蔽一切可能违反数据完整性的操作,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁。1.2乐观锁(OptimisticLock)顾名思义,就是很乐观,假设不会发生并发冲突,只在提交操作时检查是否违反数据完整性。乐观锁不能解决脏读的问题。每次拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,

    2022年10月16日
    0

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号