Java--终止/中断线程

Posted MinggeQingchun

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java--终止/中断线程相关的知识,希望对你有一定的参考价值。

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

1、使用退出标志,使线程正常退出,也就是当 run() 方法完成后线程中止

2、使用 stop() 方法强行终止线程,但是不推荐使用这个方法,该方法已被弃用

3、使用 interrupt() 方法中断线程(只是中断线程执行,终止线程的睡眠(唤醒),并未终止线程)

1、标志位

定义一个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;

        for (int i = 1; i <= 100; i++) 
            System.out.println(Thread.currentThread().getName() + "---->" + i);
        
    


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、 stop() 方法

通过查看 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() 方法会立即释放该线程所持有的所有的锁,导致数据得不到同步,出现数据不一致的问题。

// thread.stop()强行终止t线程
thread.stop();

3、interrupt() 方法中断线程

t.interrupt()方法只是中断t线程的睡眠(依靠了Java的异常处理机制),唤醒线程;t.interrupt()方法不是中断线程的执行,是唤醒线程

/**
 线程sleep睡眠,唤醒一个正在睡眠的线程
    t.interrupt();
    中断t线程的睡眠(这种中断睡眠的方式依靠了Java的异常处理机制)
    注:这个不是中断线程的执行,是终止线程的睡眠
 */
public class ThreadWakeup 
    public static void main(String[] args) 
        Thread t = new Thread(new SleepRunnable());
        t.setName("t");
        t.start();

        try 
            //5秒之后就可以输出  “t----end”;
            Thread.sleep(1000 * 5);
         catch (InterruptedException e) 
            e.printStackTrace();
        

        /**
         * 中断t线程的睡眠(这种中断睡眠的方式依靠了Java的异常处理机制)
         *
         * t.interrupt(); 采用了Java的异常处理机制,如果不想输出异常,可以注释掉e.printStackTrace();
         *
         * t----begin
         * java.lang.InterruptedException: sleep interrupted
         * 	at java.lang.Thread.sleep(Native Method)
         * 	at thread.sleep.SleepRunnable.run(ThreadWakeup.java:35)
         * 	at java.lang.Thread.run(Thread.java:748)
         * t----end
         * */
        t.interrupt();
    


class SleepRunnable implements Runnable

    /**
     * run()当中的异常不能throws,只能try catch
     * 因为run()方法在父类中没有抛出任何异常,子类不能比父类抛出更多的异常
     */
    @Override
    public void run() 
        System.out.println(Thread.currentThread().getName() + "----begin");
        try 
            Thread.sleep(1000 * 60 * 60 * 24);
         catch (InterruptedException e) 
            e.printStackTrace();
        
        //睡眠一天后才可以执行
        System.out.println(Thread.currentThread().getName() + "----end");
    

    // 其它方法可以throws
    /*public void doOther() throws Exception
    */

注:

在Thread类中有两个方法可以判断线程是否通过interrupt方法被终止。一个是静态的方法interrupted(),一个是非静态的方法isInterrupted(),这两个方法的区别是interrupted用来判断当前线是否被中断,而isInterrupted可以用来判断其他线程是否被中断

以上是关于Java--终止/中断线程的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法中断,终止或以其他方式解除(释放同步锁)一个死锁的Java线程,允许其他线程继续?

java 多线程5: java 终止线程及中断机制 (stop()interrupt() interrupted()isInterrupted())

并发基础 java线程的终止与中断

Java并发编程-如何终止线程

Java并发编程原理与实战四:线程如何中断

Java--终止/中断线程