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 阅读(...) 评论(...) 编辑 收藏

java 线程interupt stop(dep)相关推荐

  1. 四种Java线程池用法解析

    四种Java线程池用法解析 本文为大家分析四种Java线程池用法,供大家参考,具体内容如下 http://www.jb51.net/article/81843.htm 1.new Thread的弊端 ...

  2. 【java线程】锁机制:synchronized、Lock、Condition

    [Java线程]锁机制:synchronized.Lock.Condition 原创 2013年08月14日 17:15:55 标签:Java /多线程 74967 http://www.infoq. ...

  3. java线程安全总结 - 1 (转载)

    原文地址:http://www.jameswxx.com/java/java%E7%BA%BF%E7%A8%8B%E5%AE%89%E5%85%A8%E6%80%BB%E7%BB%93/ 最近想将ja ...

  4. java线程钥匙_Java多线程并发编程/锁的理解

    一.前言 最近项目遇到多线程并发的情景(并发抢单&恢复库存并行),代码在正常情况下运行没有什么问题,在高并发压测下会出现:库存超发/总库存与sku库存对不上等各种问题. 在运用了 限流/加锁等 ...

  5. 面试必问---Java线程池8大拒绝策略

    前言 谈到java的线程池最熟悉的莫过于ExecutorService接口了,jdk1.5新增的java.util.concurrent包下的这个api,大大的简化了多线程代码的开发.而不论你用Fix ...

  6. Java线程怎样映射到操作系统线程

    先说多线程模型,参考经典教材<Operating System Concepts , Silberschatz ,9th edition> 中文版是<操作系统概念,第9版> h ...

  7. java线程的优先级是数字越大优先级越高_《深入理解Java虚拟机》5分钟速成:12章(Java内存模型与线程)...

    第12章 Java内存模型与线程 前言: 1.物理机如何处理并发问题? 2.什么是Java内存模型? 3.原子性.可见性.有序性的具体含义和应用实现? 4.volatile 关键字特性? 5.基于vo ...

  8. java 线程组作用_浅析Java中线程组(ThreadGroup类)

    一.概念 Java中使用ThreadGroup类来代表线程组,表示一组线程的集合,可以对一批线程和线程组进行管理.可以把线程归属到某一个线程组中,线程组中可以有线程对象,也可以有线程组,组中还可以有线 ...

  9. 2017年50道Java线程面试题

    下面是Java线程相关的热门面试题,你可以用它来好好准备面试. 1) 什么是线程? 线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位.程序员可以通过它进行多处理器编 ...

最新文章

  1. 10组第一次作业-现代软件工程2017成员介绍
  2. ES6中import * as xxx from ‘xxx‘的作用
  3. 点击右侧导航栏,实现iframe嵌入子页面中div,滑动到最上面
  4. Minidao_1.6.2版本发布,超轻量Java持久化框架
  5. ES6-Set集合的创建
  6. 拒绝与其他码农一致!CSDN定制T让你成为最靓的仔
  7. 科技未来 | 计算机芯片如何拥有嗅觉?
  8. C/C++[codeup 2063]日期累加
  9. 记录一下自己简单的想法
  10. 家用计算机的使用说明,AWIND奇机家用无线投屏器使用说明
  11. css中自适应字体问题等
  12. Unity 复制内容到剪贴板
  13. matlab中双向二极管,基于Multisim与Matlab的二极管双T电桥仿真分析
  14. 中英对照:30句经典英语广告词欣赏
  15. 最详细的 K8S 学习笔记总结(2021最新版)
  16. 哪个dns服务器延迟最低,可以立即测出延迟最小的DNS
  17. 集成学习(上):机器学习基础task1-熟悉机器学习的三大主要任务
  18. 机遇与财富并存,一家网吧打造自己的客户数据库,后端疯狂盈利!
  19. 正是岳麓好风景,软件逢君正当时
  20. 沐阳JP1081B USB转网口 内核选项

热门文章

  1. 程序员小志偷偷用30招惊艳公司所有人,迎娶小师姐(第5招)
  2. 简单聊一聊有关就业和职业发展的话题
  3. 基于QT c++开发的音乐播放器
  4. 集合转数组 toArray()方法
  5. 【论文阅读】使用周期一致的对抗网络的非匹配的图片到图片的翻译
  6. Doris、Clickhouse、Tidb三者对比
  7. php正则字符串,php正则匹配字符串
  8. asp.net校园二手交易网站VS开发sqlserver数据库web结构c#编程计算机网页项目
  9. 手机欠费超3个月就成失信人员,请问你同不同意?
  10. invalid comparator问题