Java

【多线程】——4.安全的终止线程

2020-03-29  本文已影响0人  衰煋

安全的终止线程


线程正常执行结束,就会终止

除了正常结束外,还有什么方法终止?


设置线程终止标志

public class FlagThread extends Thread {

    /**

    * 退出标识

    */

    public volatile boolean exit = false;

    @Override

    public void run() {

        while (!exit);

        System.out.println("ThreadFlag线程退出");

    }

    public static void main(String[] args) throws Exception

    {

        FlagThread threadFlag = new FlagThread();

        threadFlag.start();

        // 主线程延迟3秒

        sleep(3000);

        // todo 终止线程thread

        threadFlag.exit = true;

        // main线程放弃cpu使用权

        // 让threadFlag线程继续执行,直到threadFlag运行完

        threadFlag.join();

        System.out.println("线程退出!");

    }

}

上面代码定义了退出标志exit,为true的时候,会退出,默认为false,在定义exit时,用volatile 修饰,这个关键字的目的是保证exit内存可见性,就是exit被修改的时候立刻对其他线程可见。

中断的方式终止线程 

当线程阻塞时,使线程处于不可运行状态时,即使主线程中该线程的退出标志设置为true,但是该线程此时根本无法检测循环标志,当然就无法立即中断。

public class InterruptThread extends Thread {

    /**

    * 退出标识

    */

    volatile boolean exit = false;

    @Override

    public void run() {

        while (!exit) {

            System.out.println(getName() + " is running");

            try {

                Thread.currentThread().join();

            } catch (InterruptedException e) {

                System.out.println("week up from block...");

                exit = true; // 在异常处理代码中修改共享变量的状态

            }

        }

        System.out.println(getName() + " is exiting...");

    }

    public static void main(String[] args) throws InterruptedException {

        InterruptThread interruptThread = new InterruptThread();

        System.out.println("Starting thread...");

        interruptThread.start();

        Thread.sleep(3000);

        System.out.println("Interrupt thread...: " + interruptThread.getName());

        // 设置退出标识为true

        interruptThread.exit = true;

        // todo 阻塞时退出阻塞状态

//        interruptThread.interrupt();

        // 主线程休眠3秒以便观察线程interruptThread的中断情况

        Thread.sleep(3000);

        System.out.println("Stopping application...");

    }

}

由图片可见代码执行到41行了,但是没有执行完。

因为主线程Thread.sleep(3000)时interruptThread执行了,代码中通过 Thread.currentThread().join();让出了cpu使用权,这时主线程继续,就算设置interruptThread,exit为true,但是interruptThread还卡在那个地方,无法检测到,所以没有向下走,主线程就继续往下走了。这时如果把38行注释打开,run方法的方法体会报错被catch,不再阻塞,这时会输出week up from block并且修改状态,被检测到,然后退出。


废弃的终止线程的方式,工作中不要用,但是可以了解一下

Thread.stop()----类似电脑直接拔掉电源,强行终止线程,后果不可预料。它会强行释放子线程持有的锁,导致被保护的资源出现线程安全问题。,会抛出一个ThreadDeath,这个继承了Error,会抛error。

Thread.suspend/Thread.resume----使线程暂停,不会释放锁的资源/resume使线程回复,suspend和resume必须成对出现,否则不起效果。但是很难控制这个先后顺序,容易造成死锁。

Runtime.runFinalizersOnExit---这个方法本身不是线程安全的



总结

终止线程的方式推荐有两种

一种是使用退出标识

另一种是设置中断

上一篇 下一篇

猜你喜欢

热点阅读