Java多线程3种中断方式和终止方式

本文介绍了Java中线程中断的三种方法:volatile修饰的退出标志、使用AtomicBoolean标记位以及interrupt()方法。同时讨论了线程终止的API过时问题,强调了stop方法的不安全性。
摘要由CSDN通过智能技术生成

一、线程中断

Java 中有以3 种方法可以中断正在运行的线程:

  1. 使用(volatile修饰)退出标志,使线程正常退出,也就是当 run() 方法完成后线程中止;
  2. 也可使用 Atomic 变量作为退出标志,同样可以实现线程的中断;
  3. 使用 interrupt() 方法中断线程(只是中断线程执行,终止线程的睡眠(唤醒),并未终止线程)

1.volatile修饰的标记位

        定义一个boolean型的标志位,在线程的run方法中根据这个标志位是true还是false来判断是否退出

/**
 * 使用标志位终止线程
 * */
public class ThreadStop {
    public static void main(String[] args) {
        ThreadStopRunnable runnable = new ThreadStopRunnable();
        Thread t = new Thread(runnable);
        t.setName("t");
        t.start();

        try {
            Thread.sleep(1000 * 5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        //执行5秒之后终止线程,终止t线程的执行,将标记修改为false即可
        runnable.runFlag = false;

        System.out.println(Thread.currentThread().getName() + "\t" + "main is over");
    }
}

class ThreadStopRunnable implements Runnable {
    //volatile修饰符用来保证其它线程读取的总是该变量的最新的值
    public volatile boolean runFlag = true;

    @Override
    public void run() {
        for (int i = 1; i <= 100; i++) {
            if (runFlag){
                System.out.println(Thread.currentThread().getName() + "---->" + i);

                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }else {
                //执行终止线程之前的代码,如保存数据等

                return;
            }
        }
    }
}

2.AtomicBoolean标记位

        可以使用AtomicBoolean作为标记位,省去volatile关键字修饰。

/**
 * 使用标志位终止线程
 * */
public class ThreadStop {
    public static void main(String[] args) {
        ThreadStopRunnable runnable = new ThreadStopRunnable();
        Thread t = new Thread(runnable);
        t.setName("t");
        t.start();

        try {
            Thread.sleep(1000 * 5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        //执行5秒之后终止线程,终止t线程的执行,将标记修改为false即可
        runnable.runFlag.set(false);

        System.out.println(Thread.currentThread().getName() + "\t" + "main is over");
    }
}

class ThreadStopRunnable implements Runnable {
    //volatile修饰符用来保证其它线程读取的总是该变量的最新的值
    public AtomicBoolean runFlag = new AtomicBoolean(true);

    @Override
    public void run() {
        for (int i = 1; i <= 100; i++) {
            if (runFlag.get()){
                System.out.println(Thread.currentThread().getName() + "---->" + i);

                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }else {
                //执行终止线程之前的代码,如保存数据等

                return;
            }
        }
    }
}

3.interrupt() 中断

        使用interrupt()方法,仅仅是给线程打上中断标记位,并没有实际中断线程(把中断的权利交给线程本身,更安全)

        interrupt() 正在睡眠的线程会抛出InterruptedException异常。

/**
 * 使用标志位终止线程
 * */
public class ThreadStop {
    public static void main(String[] args) {
        ThreadStopRunnable runnable = new ThreadStopRunnable();
        Thread t = new Thread(runnable);
        t.setName("t");
        t.start();

        try {
            Thread.sleep(1000 * 5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        t.interrupt();
        System.out.println(Thread.currentThread().getName() + "\t" + "main is over");
    }
}

class ThreadStopRunnable implements Runnable {

    @Override
    public void run() {
        for (int i = 1; i <= 100; i++) {
            if (!Thread.currentThread().isInterrupted()){
                System.out.println(Thread.currentThread().getName() + "---->" + i);

                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    e.printStackTrace();
                }
            }else {
                //执行终止线程之前的代码,如保存数据等

                return;
            }
        }
    }
}

t---->1
t---->2
t---->3
t---->4
t---->5
main    main is over
java.lang.InterruptedException: sleep interrupted
    at java.lang.Thread.sleep(Native Method)
    at org.mark.spring.test.ThreadStopRunnable.run(ThreadStop.java:35)
    at java.lang.Thread.run(Thread.java:748)

二、线程终止

        通过查看 JDK 的 API,我们会看到 java.lang.Thread 类型提供了一系列的方法如 start()、stop()、resume()、suspend()、destory()等方法来管理线程。但是除了 start() 之外,其它方法都被声名为已过时(deprecated)

        虽然 stop() 方法确实可以停止一个正在运行的线程,但是这个方法是不安全的,而且该方法已被弃用,最好不要使用它。
JDK 文档中还引入用一篇文章来解释了弃用这些方法的原因:《Why are Thread.stop, Thread.suspend and Thread.resume Deprecated?》

为何弃用stop:

1、调用 stop() 方法会立刻停止 run() 方法中剩余的全部工作,包括在 catch 或 finally 语句中的,并抛出ThreadDeath异常(通常情况下此异常不需要显示的捕获),因此可能会导致一些清理性的工作的得不到完成,如文件,数据库等的关闭

2、调用 stop() 方法会立即释放该线程所持有的所有的锁,导致数据得不到同步,出现数据不一致的问题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值