首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >1.7停止线程

1.7停止线程

作者头像
用户1134788
发布于 2017-12-27 02:23:10
发布于 2017-12-27 02:23:10
2K00
代码可运行
举报
运行总次数:0
代码可运行

线程停止:在线程处理完任务之前,停掉正在做的操作,也就是放弃当前操作。

java中有三种方法可以实现线程的停止:

  1. 使用退出标志,使线程正常退出,也就是当run方法执行完后线程终止。
  2. 使用stop强行终止线程。但是不推荐这个方法,因为stop与suspend以及resume一样,都是作废过期的方法,使它们产生不可预期的结果。
  3. 使用interrupt()方法中断线程。该方法不会终止一个线程,还需要加入一个判断才能够完成线程的终止。

1.7.1停不了的线程

本例中调用interrupt()方法来停止线程,但是interrupt()方法并不像循环中的break关键字一样可以立即起效,interrupt()方法仅仅是在当前线程中打了一个停止的标记,并没有真正停止线程。

线程代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class MyThread extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 500000; i++) {
            System.out.println("i = " + (i + 1));
        }
    }
}

执行代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Main {
    public static void main(String[] args) {
        try {
            MyThread mt = new MyThread();
            mt.start();
            mt.sleep(2000);
            mt.interrupt();
        } catch (Exception e) {
            System.out.println("main Catch");
            e.printStackTrace();
        }
    }
}

执行结果:

实际上代码执行了50000行,并没有出现线程的停止。

1.7.2判断线程是否是停止状态:

在Java的SDK中,Thread.java类里提供了两种方法判断线程是否停止

this.interrupted()的代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Thread1 extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 50; i++) {
            System.out.println("i = " + (i + 1));
        }
    }
}

执行代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Main {
    public static void main(String[] args) {
        try {
            Thread1 t1 = new Thread1();
            t1.start();
            t1.sleep(1000);
            t1.interrupt();
            System.out.println("是否停止了1? = " + Thread.interrupted());
            System.out.println("是否停止了2? = " + Thread.interrupted());
        } catch (Exception e) {
            System.out.println("main catch");
            e.printStackTrace();
        }
    }
}

执行结果:

分析:从打印结果来看线程并没有中断。this.interrupted()的解释是:测试当前线程是否中断,根据代码可以判断当前的线程为“main”线程。这里肯定是没有中断的,所以返回false。

使main线程产生中断:

执行代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Main {
    public static void main(String[] args) {
        Thread.currentThread().interrupt();
        System.out.println("是否停止了1 ? = " + Thread.interrupted());
        System.out.println("是否停止了2 ? = " + Thread.interrupted());
        System.out.println("end!");
    }
}

执行结果:

为什么这里第二次判断的时候返回false呢?

interrupted()方法的解释:测试当前线程是否已经中断。线程的中断状态由该方法去除。

可以预见,如果连续两次调用该方法,则第二次调用将返回false(在第一次调用后已经清楚了线程的中断状态,且第二次调用在中断状态前,所以返回false)

this.isInterrupted():

该方法声明如下:

public boolean isInterrupted()

注:不是静态方法。

线程代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Thread1 extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 50; i++) {
            System.out.println("i = " + (i + 1));
        }
    }
}

执行代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Main {
    public static void main(String[] args) {
        try {
            Thread1 thread = new Thread1();
            thread.start();
            Thread.sleep(1000);
            thread.interrupt();
            System.out.println("是否停止1 ? = " + thread.isInterrupted());
            System.out.println("是否停止2 ? = " + thread.isInterrupted());
        } catch (Exception e) {
            System.out.println("main catch");
            e.printStackTrace();
        }
        System.out.println("end!");
    }
}

结果:

????惊了这为什么就不一样呢????(一脸懵逼。代码应该是没问题的,有没有大佬来指点一下。)(我修改了休眠时间什么的还是现实false。。反倒是去掉休眠时间会返回true,我有点烦)

  1. this.interrupted():测试当前线程是否已经是中断状态,执行后具有将状态标志清楚为false的功能。
  2. this.isInterrupted():测试线程Thread对象是否已经是中断状态,但不能清楚状态标志。

1.7.3能停止的线程——异常法:

线程代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Thread2 extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 500000; i++) {
            if (this.interrupted()) {
                System.out.println("已经是停止状态! 我要退出了!");
                break;
            }
            System.out.println("i = " + (i + 1));
        }
    }
}

运行代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Main {
    public static void main(String[] args) {
        try {
            Thread2 thread = new Thread2();
            thread.start();
            Thread.sleep(2000);
            thread.interrupt();
        } catch (Exception e) {
            System.out.println("main catch");
            e.printStackTrace();
        }
        System.out.println("end!");
    }
}

 结果:

注:实际上此时如果线程的for循环外还有代码的话还是会继续执行的(Thread.interruped()调用后会移除线程的停止状态,即线程会继续调用run()内部的代码)

线程代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Thread3 extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 500000; i++) {
            if (Thread.interrupted()) {
                System.out.println("已经是停止状态了,我要退出了!");
                break;
            }
            System.out.println("i = " + (i + 1));
        }
        System.out.println("我被输出说明线程已经结束停止状态,并继续执行。");
    }
}

执行代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Main {
    public static void main(String[] args) {
        try {
            Thread3 thread = new Thread3();
            thread.start();
            Thread.sleep(2000);
            thread.interrupt();
        } catch (Exception e) {
            System.out.println("main catch");
            e.printStackTrace();
        }
        System.out.println("end!");
    }
}

执行结果:

如果解决后续语句继续输出的问题?

这时候利用的就是抛出异常来解决。(但是我个人认为,你换一个判断方法不就行了?调用对象的this.isInterrupt(),不过由于这是展示如何停止一个线程的,标题名还是异常法。。就这样吧)

线程代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Thread4 extends Thread {
    @Override
    public void run() {
        try {
            for (int i = 0; i < 500000; i++) {
                if (Thread.interrupted()) {
                    System.out.println("已经停止了!我要退出了!在此时抛出异常,使线程结束。");
                    throw new InterruptedException();
                }
                System.out.println("i = " + (i + 1));
            }
            System.out.println("我在for循环下面,是本来可以执行的代码。");
        } catch (Exception e){
            System.out.println("进入线程代码的异常处理中");
            e.printStackTrace();
        }
    }
}

执行代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Main {
    public static void main(String[] args) {
        try {
            Thread4 thread = new Thread4();
            thread.start();
            Thread.sleep(2000);
            thread.interrupt();
        } catch (Exception e) {
            System.out.println("main catch");
            e.printStackTrace();
        }
        System.out.println("end!");
    }
}

执行结果:

 1.7.4在沉睡中停止:

如果线程在sleep()状态下停止线程,会有什么效果呢?

线程代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Thread5 extends Thread {
    @Override
    public void run() {
        try {
            System.out.println("run begin");
            Thread.sleep(20000000);
            System.out.println("run end");
        } catch (Exception e) {
            System.out.println("在沉睡中被停止!进入catch 停止状态为:" + this.isInterrupted());
            e.printStackTrace();
        }
    }
}

执行代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Main {
    public static void main(String[] args) {
        try {
            Thread5 thread = new Thread5();
            thread.start();
            Thread.sleep(2000);
            thread.interrupt();
        } catch (Exception e) {
            System.out.println("main catch");
            e.printStackTrace();
        }
        System.out.println("end!");
    }
}

 执行结果:

从结果看,在sleep下停止某一线程,会进入catch语句,并且清楚之前的状态值,使之变成false。

这次是先停止,然后再睡眠:

线程代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Thread6 extends Thread {
    @Override
    public void run() {
        try {
            for (int i = 0; i < 100000; i++) {
                System.out.println("i=" + (i + 1));
            }
            System.out.println("run begin");
            Thread.sleep(200000);
            System.out.println("run end");
        } catch (Exception e) {
            System.out.println("先interrupt(),再遇到了sleep!进入catch");
            e.printStackTrace();
        }
    }
}

执行代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Main {
    public static void main(String[] args) {
        Thread6 thread = new Thread6();
        thread.start();
        thread.interrupt();
        System.out.println("end!");
    }
}

执行结果:

也就是说。不论是先睡眠,然后再睡眠中被停止,还是先停止,在睡眠。都会报错。

1.7.5能停止的线程——暴力停止:

使用stop()方法停止线程是暴力的。

线程代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Thread7 extends Thread {
    private int i = 0;

    @Override
    public void run() {
        try {
            while (true) {
                i++;
                System.out.println("i=" + i);
                Thread.sleep(1000);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

执行代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Main {
    public static void main(String[] args) {
        try {
            Thread7  thread = new Thread7();
            thread.start();
            Thread.sleep(5000);
            thread.stop();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

执行结果:

 1.7.6方法stop()与java.lang.ThreadDeath异常:

调用stop()方法时,会抛出java.lang.ThreadDeath异常,但在通常情况下,此异常不需要显示地捕捉。

创建线程代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Thread8 extends Thread {
    @Override
    public void run() {
        try {
            this.stop();
        } catch (ThreadDeath e) {
            System.out.println("进入了catch()方法中");
            e.printStackTrace();
        }
    }
}

 执行代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Main {
    public static void main(String[] args) {
        Thread8 thread = new Thread8();
        thread.start();
    }
}

 执行结果:

注:stop()方法已经作废,因为如果强制停止线程会导致一些清理的工作无法完成,另外一种情况就是对锁定的对象进行了“解锁”,导致数据得不到同步的处理,出现数据不一致的问题。

1.7.7释放锁的不良后果:

使用stop()释放锁将会给数据造成不一致性的结果。如果出现这种情况,程序执行的数据就会遭到破坏,最终导致程序的执行出现异常。

同步类代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class SynchronizedObject {
    private String username = "a";
    private String password = "aa";

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    synchronized public void printString(String username,String password) {
        try {
            this.username = username;
            Thread.sleep(100000);
            this.password = password;
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

线程代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Thread9 extends Thread {
    private SynchronizedObject object;

    public Thread9(SynchronizedObject object) {
        this.object = object;
    }

    @Override
    public void run() {
        object.printString("b","bb");
    }
}

执行代码: 

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Main {
    public static void main(String[] args) {
        try {
            SynchronizedObject object = new SynchronizedObject();
            Thread9 thread = new Thread9(object);
            thread.start();
            Thread.sleep(500);
            thread.stop();
            System.out.println(object.getUsername() + "  " + object.getPassword());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

 执行结果:

注:由于stop()方法将锁释放,此时还没有对run()的方法调用完毕,导致数据出现不一致现象。(仅仅username被修改,线程在休眠的过程中被杀死,导致密码的修改没有进行)。

1.7.8使用return停止线程:

使用interrupt()与return结合使用也能实现停止线程的效果。

线程代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Thread10 extends Thread {
    @Override
    public void run() {
        while (true) {
            if (this.isInterrupted()) {
                System.out.println("停止了!");
                return;
            }
            System.out.println("timer = " + System.currentTimeMillis());
        }
    }
}

 执行代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Main {
    public static void main(String[] args) {
        try {
            Thread10 thread = new Thread10();
            thread.start();
            Thread.sleep(2000);
            thread.interrupt();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

执行结果:

从目前来看,这是一种很合理的方式来实现线程的停止。如果以后能看到更多的东西会回来对笔记进行修正的。

源码地址:https://github.com/lilinzhiyu/threadLearning

本文内容是书中内容兼具自己的个人看法所成。可能在个人看法上会有诸多问题(毕竟知识量有限,导致认知也有限),如果读者觉得有问题请大胆提出,我们可以相互交流、相互学习,欢迎你们的到来,心成意足,等待您的评价。

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

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

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

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

评论
登录后参与评论
暂无评论
推荐阅读
一道课后练习题背后的知识点
前两天做了一个随机生成密码的课后练习题,题目挺简单,但是这个题目却有两个比较重要的知识点Random和String模块,今天就跟大家聊一聊这两个知识点。话不多说,我们开始吧。
PM小王
2019/07/02
5970
一道课后练习题背后的知识点
软件测试|Python random模块,超乎想象的强大
Python的random模块是一个非常强大的工具,用于生成随机数和随机选择。它提供了许多函数和方法,可以满足各种随机化需求。本文将介绍random模块的基本功能和常见用法,以帮助读者更好地理解和利用这个模块。
霍格沃兹测试开发Muller老师
2023/09/07
2510
生成一个指定长度的随机数
生成随机数在日常工作中的使用率也很高。虽说Python标库自带了生成随机数的功能。但是我想写一个函数,既可以生成数字,又可以生成字符串。而且还可以指定长度,自由自在的生成需要的数据。把它放在我的工具库中,工作过程中需要的时候,随时随地调用,可不快哉。
TalkPython
2020/05/27
1.5K0
Python | Python 生成验证码(本篇文章无干货)
爬虫和验证码就是天生的冤家,用 Python 生成验证码应该是用 Python 对抗验证码的第一步,所以今天先来研究研究如何用 Python 生成一个便于我们入手的验证码。
咸鱼学Python
2020/05/28
1.3K0
一日一技:在 Python 里面的常用常量字符串
曾经,当我想实现:从24个小写字母中随机选择一个字母的时候,我是这样写代码的: import random letter = random.choice('qwertyuiopasdfghjklzxcvbnm') 后来,我知道了,原来代码可以这样写: import random import string letter = random.choice(string.ascii_lowercase) string模块包含了我们常用的一些常量字符串: 大小写字母:string.ascii_letters
青南
2019/12/17
7620
python随机生成字符串学习
random.choice从序列中获取一个随机元素。其函数原型为:random.choice(sequence)。参数sequence表示一个有序类型。这里要说明 一下:sequence在python不是一种特定的类型,而是泛指一系列的类型。list, tuple, 字符串都属于sequence。有关sequence可以查看python手册数据模型这一章。下面是使用choice的一些例子:
py3study
2020/01/09
1.4K0
小实战_02_批量生成指定格式文件夹
如果你也有相同问题,希望文章能帮到你,如果你有其他相关问题或者想法,欢迎留言交流。
老表
2023/09/09
1750
小实战_02_批量生成指定格式文件夹
Python random() 函数
import random import string # 随机整数: print random.randint(1, 50) # 随机选取0到100间的偶数: print random.randrange(0, 101, 2) # 随机浮点数: print random.random() print random.uniform(1, 10) # 随机字符: print random.choice('abcdefghijklmnopqrstuvwxyz!@#$%^&*()') # 多个字符中生成
SingYi
2022/07/14
2330
Python - random 库的详细使用
前言 为啥突然写这个?因为用到就写呗,感觉对生成数据很有用,之前都是百度别人的,今天来对着官方文档写,超级标准! 这边只讲常用的,看了下文档还有什么数学方法,太高级好像用不上 返回整数 random.randrange 语法格式 两种写法 random.randrange(stop) random.randrange(start, stop[, step]) start:起始数字,包含(取得到 start 这个值) stop:末尾数字,不包含(取不到 stop 这个值) step:步长 实际栗子 # 栗子一
小菠萝测试笔记
2021/06/10
5760
Python-random函数用法
Python标准库中的random函数,可以生成随机浮点数、整数、字符串,甚至帮助你随机选择列表序列中的一个元素,打乱一组数据等。 random中的一些重要函数的用法:
全栈程序员站长
2022/08/15
5500
python生成随机四位数和AttributeError: module 'random' has no attribute 'sample'
python生成随机四位数和AttributeError: module 'random' has no attribute 'sample'
oktokeep
2024/10/09
1350
移动并重命名2000个文件,Python,3秒
今天介绍的案例是如何利用Python来自动化移动、修改、重命名文件/夹,这样的操作在日常办公中经常会用到,若能掌握用Python实现将会大大提高效率!
刘早起
2021/02/05
1.7K0
Python学习杂记_3_字符串操作的常用方法
字符串是可以通过下标来进行取值的,但是由于字符串是不可变变量,不能通过下标来修改它的值(形式如 字符串[下标]),下标从0开始,最大下标值是字符串长度减1,即len(string)-1
呆呆
2021/05/25
5350
超详解—Python 字符串详解——基础篇
Python中可以使用单引号(')、双引号(")和三引号(''' 或 """)来定义字符串。虽然它们都可以用来表示字符串,但在某些情况下,它们有各自的优势和用法。
小李很执着
2024/06/15
5780
常用的生成测试数据的python脚本,用了都说好
生成接口自动化测试数据时,Python提供了丰富的库和工具来帮助我们创建各种类型的数据, 以下是常用的Python脚本示例,用于生成不同类型的测试数据。
可可的测试小栈
2024/11/23
3320
常用的生成测试数据的python脚本,用了都说好
python中字符串的基本操作汇总
字符串是文本操作的核心,在python中字符串是string类的实例,在string模块中,定义了很多的常量
生信修炼手册
2020/05/07
6390
Python 随机字符串
当调用方法 choice(string.ascii_uppercase) 的意思是将会随机从大写字符中挑选出一个字符。
HoneyMoose
2021/03/19
7040
Python 随机字符串
python/测试/测开-面试准备第1天
解决方案 从今天开始我们开始整理面试题,开始刷题【python】【测试】相关。 面试题01:如何使用random模块生成随机数、实现随机乱序和随机抽样? 点评:送人头的题目,因为Python标准库中的常用模块应该是Python开发者都比较熟悉的内容,这个问题回如果答不上来,整个面试基本也就砸锅了。 python random模块解析 random.random()函数可以生成[0.0, 1.0)之间的随机浮点数。 random.uniform(a, b)函数可以生成[a, b]或[b, a]之间的随机浮点数
测试开发囤货
2021/11/29
5510
Python制作图片验证码?也就三行代码罢了
现在验证码的种类真的是越来越多,短信验证码、语音验证码、图片验证码、滑块验证码 ... 我们在 PC 的网页端或者手机上的 app 进行登录或者注册时,应该总会遇见图片验证码,比如下面这类:
奶糖猫
2020/08/11
1.1K0
Python制作图片验证码?也就三行代码罢了
[oeasy]python080如何生成验证码_随机数字密码_真随机
import random # 生成一个6位的随机数字,每位数字可以是0-9 random_number = "" for _ in range(6): random_digit = random.randint(0, 9) random_number += str(random_digit) # 显示生成的随机数字 print(f"生成的6位随机数字是: {random_number}") 结果
oeasy
2025/03/29
1540
[oeasy]python080如何生成验证码_随机数字密码_真随机
推荐阅读
相关推荐
一道课后练习题背后的知识点
更多 >
LV.1
这个人很懒,什么都没有留下~
目录
  • 1.7.1停不了的线程
  • 1.7.2判断线程是否是停止状态:
    • this.interrupted()的代码:
    • this.isInterrupted():
  • 1.7.3能停止的线程——异常法:
  •  1.7.4在沉睡中停止:
  • 1.7.5能停止的线程——暴力停止:
  •  1.7.6方法stop()与java.lang.ThreadDeath异常:
  • 1.7.7释放锁的不良后果:
  • 1.7.8使用return停止线程:
    • 本文内容是书中内容兼具自己的个人看法所成。可能在个人看法上会有诸多问题(毕竟知识量有限,导致认知也有限),如果读者觉得有问题请大胆提出,我们可以相互交流、相互学习,欢迎你们的到来,心成意足,等待您的评价。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档