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

    你可能感兴趣的文章
    MySQL两千万数据优化&迁移
    查看>>
    MySql中 delimiter 详解
    查看>>
    MYSQL中 find_in_set() 函数用法详解
    查看>>