博客
关于我
java更加优雅并且主动控制线程中断
阅读量:786 次
发布时间:2019-03-25

本文共 2880 字,大约阅读时间需要 9 分钟。

一、stop()方法

提到中断线程,首先想到的可能是stop()方法。然而,这个方法已被官方退化为不推荐使用。以下是官方给出的原因:

  • 停止执行:调用stop()方法会立即停止run()方法中剩余的所有工作,包括catch或finally语句中的内容,并抛出ThreadDeath异常。这种异常通常情况下不需要显式捕获,可能导致文件、数据库等资源未能完成正确关闭。

  • 锁定问题:stop()方法立即释放线程所持有的所有锁定,导致数据同步错误,可能造成数据不一致。

  • 因此,我们不能使用stop()方法来中断线程。


    二、interrupt()方法

    使用interrupt()方法能否中断线程?答案是否定的。

    interrupt()方法只是设置线程的一个标志,便通知线程可以中断,但实际中断时机由线程自己决定。

    以下是通过一个简单示例来理解:

    public class InterruptedTask implements Runnable {    @Override    public void run() {        Thread currentThread = Thread.currentThread();        while (true) {            if (currentThread.isInterrupted()) {                break;            }            try {                Thread.sleep(100);            } catch (InterruptedException e) {                e.printStackTrace();                // 在这里,我们需要重新设置中断标记                currentThread.interrupt();            }        }    }}public class InterruptedTest {    public static void main(String[] args) {        InterruptedTask task = new InterruptedTask();        Thread thread = new Thread(task);        thread.start();        try {            Thread.sleep(1000);        } catch (InterruptedException e) {            e.printStackTrace();        }        thread.interrupt();    }}

    运行结果显示,线程并未退出。这是因为:

    • InterruptedException异常:Thread.sleep()方法会在被中断时抛出InterruptedException异常。
    • JVM在抛出异常时会重置线程的中断标记(currentThread.isInterrupted()返回false),导致线程无法再次受中断影响。

    要正确中断线程,必须在捕获异常后重新设置中断标记:

    public class InterruptedTask implements Runnable {    @Override    public void run() {        Thread currentThread = Thread.currentThread();        while (true) {            if (currentThread.isInterrupted()) {                break;            }            try {                Thread.sleep(100);            } catch (InterruptedException e) {                e.printStackTrace();                // 重新设置中断标记                currentThread.interrupt();            }        }    }}

    三、标志位中断线程

    为了更好地控制线程的中断,可以使用自定义标志位。例如,在服务器程序中,线程可能进入一个持续接收客户端请求的循环,使用标志位来终止线程:

    public class ServerThread extends Thread {    public volatile boolean exit = false; // 保证多线程环境下读取最新值    @Override    public void run() {        ServerSocket serverSocket = new ServerSocket(8080);        while (!exit) {            try {                Socket socket = serverSocket.accept();                // 处理客户端请求                socket.close();            } catch (IOException e) {                // 处理socket异常            }        }    }    public static void main(String[] args) {        ServerThread server = new ServerThread();        server.start();        try {            // 做一些运算            Thread.sleep(1000);        } catch (InterruptedException e) {            e.printStackTrace();        } finally {            server.exit = true; // 设置标志位终止线程        }    }}

    在这种方式下,我们可以主动控制线程何时中断,适用于需要定制化控制的场景。


    总结

    中断线程的方法有三个:

  • 已弃用的stop()方法。
  • 通过interrupt()设置中断标记,但线程中断由运行环境决定。
  • 使用自定义标志位主动控制线程终止。
  • 根据需求选择合适的方法是关键。标志位方法提供了更高的灵活性,适合主动控制线程终止的情况。

    转载地址:http://sbsuk.baihongyu.com/

    你可能感兴趣的文章
    PHP利用正则表达式实现手机号码中间4位用星号(*)替换显示
    查看>>
    PHP加密与安全的最佳实践
    查看>>
    PHP加速器eaccelerator导致php-fpm进程卡死原因分析
    查看>>
    PHP区分 企业微信浏览器 | 普通微信浏览器 | 其他浏览器
    查看>>
    php原生代码怎么连表查询,PHP tp5中使用原生sql查询代码实例
    查看>>
    PHP去掉转义符
    查看>>
    php去除字符串开头或末尾的字符(例如逗号)
    查看>>
    php反射api
    查看>>
    PHP反射ReflectionClass、ReflectionMethod 入门教程
    查看>>
    PHP反射机制
    查看>>
    php取当天的最后一秒_Docker快速搭建PHP开发环境详细教程
    查看>>
    php取绝对值
    查看>>
    PHP变量内容的获取
    查看>>
    php各种常用的算法
    查看>>
    php各种缓存策略对比
    查看>>
    RabbitMQ高级特性 - 消息分发(限流、负载均衡)
    查看>>
    php后台“爬虫”模拟登录第三方系统
    查看>>
    php后台的在控制器中就可以实现阅读数增加
    查看>>
    php命令行生成项目结构
    查看>>
    php命名空间
    查看>>