博客
关于我
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/

    你可能感兴趣的文章
    Qt笔记——QMutex&QWaitCondition处理生产者消费者模式
    查看>>
    Qt笔记——QLable+QPixmap图片缩放踩坑
    查看>>
    Qt笔记——foreach与forever
    查看>>
    QT程序怎么挪到Linux下,linux+Qt程序如何打包发布
    查看>>
    Qt知识:视图框架QGraphicsWidget详解
    查看>>
    SpringBoot中项目启动及定时任务缓存数据库常用数据至内存变量并转换后高频调用
    查看>>
    Qt知识: 画刷风格
    查看>>
    QT的OpenGL渲染窗QOpenGLWidget Class
    查看>>
    QT的C++程序加载动态链接库DLL(Linux下是so)的方式
    查看>>
    QT界面操作1:如何跟踪鼠标位置?
    查看>>
    Qt环境搭建(Visual Studio)
    查看>>
    QT点击"X"按钮,调用closeEvent()函数来实现调用特定事件(附:粗略介绍QT的信号与槽的使用方法)...
    查看>>
    QT样式表——url路径
    查看>>
    QT数据库(三):QSqlQuery使用
    查看>>
    QT教程5:消息框
    查看>>
    SpringBoot中集成阿里开源缓存访问框架JetCache实现声明式实例和方法缓存
    查看>>
    pom.xml中提示web.xml is missing and <failonmissingw>...
    查看>>
    Pomelo开发中Web客户端开发API简介
    查看>>
    QT教程2:QT5的体系构架
    查看>>
    PON架构(全光网络)
    查看>>