美文网首页
Java停止线程的几种方式

Java停止线程的几种方式

作者: Bfmall | 来源:发表于2023-04-16 17:24 被阅读0次

1、正常运行结束

所谓正常运行结束,我的理解就是程序正常运行结束,线程自动结束。

2. 使用退出标志退出线程

一般run()方法执行完,线程就会正常结束,然而腻,常常有些线程是伺服线程。他们需要长时间的运行,只有在外部某些条件满足的情况下,才能关闭这些线程。使用一个变量来控制循环,例如:最直接的方法就是设一个boolean类型的标志,并通过设置这个标志位true或false来控制while循环是否退出,下面放代码:

private class ThreadE extends Thread {
        private volatile  boolean isRunning = true;

        public void setRunning(boolean isRunning) {
            this.isRunning = isRunning;
        }

        @Override
        public void run() {
            super.run();
            int i=0;
            while(isRunning) {
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                i ++;
                Log.i(TAG, "ThreadE==>i="+i);
            }
        }
    }

    private void testThread() {
        ThreadE threadE = new ThreadE();
        threadE.start();
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //加入变量可以正常停止线程
        threadE.setRunning(false);
    }

这里定义了一个是否正在运行的标志isRunning,当isRunning为true时(默认为true),线程正在运行,当isRunning为false时,while循环退出。在定义isRunning时使用了一个Java关键字volatile,这个关键字的目的是使isRunning同步,也就是说在同一时刻只能由一个线程来修改isRunning的值。

输出结果:

ThreadE==>i=1
ThreadE==>i=2
ThreadE==>i=3
ThreadE==>i=4
ThreadE==>i=5
ThreadE==>i=6
ThreadE==>i=7
ThreadE==>i=8
ThreadE==>i=9
ThreadE==>i=10
ThreadE==>thread run end

可见线程正常退出了。

3.Interrupt方法结束线程

(3.1)首先看一个调用intterrupt方法中断不了的例子:

    private class ThreadF extends Thread {

        @Override
        public void run() {
            super.run();
            int i=0;
            while(!isInterrupted()) {
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    //此处捕捉异常之后,不做任何操作
                }
                i ++;
                Log.i(TAG, "ThreadF==>i="+i+", isInterrupted="+isInterrupted());
            }
            Log.d(TAG, "ThreadF==>thread end...isInterrupted="+isInterrupted());
        }
    }

    private void testThread05() {
        ThreadF threadF = new ThreadF();
        threadF.start();
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        threadF.interrupt();

        //或者调用stop中断异常
        /**try {
            //调用stop会抛出异常Caused by: java.lang.UnsupportedOperationException,
            //加上try...catch即可
            threadD.stop();
        } catch (Exception e) {
            e.printStackTrace();
        }**/
    }

输出如下:

ThreadF==>i=1, isInterrupted=false
ThreadF==>i=2, isInterrupted=false
ThreadF==>i=3, isInterrupted=false
ThreadF==>i=4, isInterrupted=false
ThreadF==>i=5, isInterrupted=false
ThreadF==>i=6, isInterrupted=false
ThreadF==>i=7, isInterrupted=false
ThreadF==>i=8, isInterrupted=false
ThreadF==>i=9, isInterrupted=false

......

ThreadF==>i=200, isInterrupted=false
ThreadF==>i=201, isInterrupted=false
......

此时调用interrrupt或stop方法无法结束线程,

看下面两种方法的解决方案:

(3.2)方法一:

线程处于阻塞状态:如使用了sleep,同步锁的wait(),socket中的receiver(),accept()等方法时,会使线程处于阻塞状态。当调用线程interrupt()方法时,会抛出InterruptException异常。阻塞中的那个方法抛出这个异常,通过代码可以捕获该异常,然后跳出循环状态,从而让我们有机会结束这个线程的执行。通常有些小伙伴认为只要调用interrupt方法,线程就会结束,实际上是不正确的,一定要先捕获InterruptException异常之后通过break来跳出循环,才能正常结束run()方法。

private class ThreadF extends Thread {

        @Override
        public void run() {
            super.run();
            int i=0;
            while(!isInterrupted()) {
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    //当线程调用interrupt中断线程时,此处捕捉到异常,并通过break跳出循环也可以结束线程
                    Log.i(TAG, "catch execption...break while loop...");
                    break;
                }
                i ++;
                Log.i(TAG, "ThreadF==>i="+i+", isInterrupted="+isInterrupted());
            }
            Log.d(TAG, "ThreadF==>thread end...isInterrupted="+isInterrupted());
        }
    }

    private void testThread05() {
        ThreadF threadF = new ThreadF();
        threadF.start();
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //调用interrupt中断线程
        threadF.interrupt();
    }

输出结果:

ThreadF==>i=1, isInterrupted=false
ThreadF==>i=2, isInterrupted=false
ThreadF==>i=3, isInterrupted=false
ThreadF==>i=4, isInterrupted=false
ThreadF==>i=5, isInterrupted=false
ThreadF==>i=6, isInterrupted=false
ThreadF==>i=7, isInterrupted=false
ThreadF==>i=8, isInterrupted=false
ThreadF==>i=9, isInterrupted=false
catch execption...break while loop...
ThreadF==>thread end...isInterrupted=false //可见跳出循环之后,isInterrupted依然为false

线程结束。

(3.3)方法二:

和方式一很相似,也是通过捕捉InterruptedException异常来结束线程,只不过在捕获异常之后,再次调用interrupt()方法来结束的,对方式一代码更改如下:

private class ThreadF extends Thread {

        @Override
        public void run() {
            super.run();
            int i=0;
            while(!isInterrupted()) {
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    //当主动调用interrupt时,就能捕捉中断异常,再次调用interrupt即可中断
                    interrupt();
                    Log.i(TAG, "catch exception...isInterrupted="+isInterrupted());
                }
                i ++;
                Log.i(TAG, "ThreadF==>i="+i+", isInterrupted="+isInterrupted());
            }
            Log.d(TAG, "ThreadF==>thread end...isInterrupted="+isInterrupted());
        }
    }

    private void testThread05() {
        ThreadF threadF = new ThreadF();
        threadF.start();
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        threadF.interrupt();
    }

输出结果:

ThreadF==>i=1, isInterrupted=false
ThreadF==>i=2, isInterrupted=false
ThreadF==>i=3, isInterrupted=false
ThreadF==>i=4, isInterrupted=false
ThreadF==>i=5, isInterrupted=false
ThreadF==>i=6, isInterrupted=false
ThreadF==>i=7, isInterrupted=false
ThreadF==>i=8, isInterrupted=false
ThreadF==>i=9, isInterrupted=false
catch execption...break while loop...
ThreadF==>i=10, isInterrupted=true
ThreadF==>thread end...isInterrupted=true//再次调用interrupt()方法之后,isInterrupted为true了

4.stop()方法终止线程(不安全)

这个各位小伙伴应该在学习中都有用过吧,我们可以直接使用thread.stop()来强行终止线程,但是stop()方法是很危险的,就想突然关闭电源一样。这样子可能机会产生不可预料的结果,不安全主要是:

thread.stop()调用之后,创建子线程的线程就会抛出ThreadDeatherror的错误,并且会释放子线程所持有的所有锁。一般任何进行加锁的代码块,都是为了保护数据的一致性,如果在调用thread.stop()后导致了该线程所持有的所有的锁突然释放,那么被保护的数据就可能呈现不一致性,其他线程在使用这些被破坏的数据时,有可能导致一些很奇怪的应用程序错误。因此,并不推荐使用stop()方法来终止线程。

————————————————

参考:
https://blog.csdn.net/weixin_44118963/article/details/119721513
https://segmentfault.com/a/1190000039696074?sort=newest

相关文章

网友评论

      本文标题:Java停止线程的几种方式

      本文链接:https://www.haomeiwen.com/subject/xuloddtx.html