如何停止线程?

2020-04-05  本文已影响0人  AD刘涛

interrupt ( )

原理介绍:

public void interrupt()

Interrupts this thread.

Unless the current thread is interrupting itself, which is always permitted, the checkAccess method of this thread is invoked, which may cause a SecurityException to be thrown.

If this thread is blocked in an invocation of the wait(), wait(long), or wait(long, int) methods of the Object class, or of the join(), join(long), join(long, int), sleep(long), or sleep(long, int), methods of this class, then its interrupt status will be cleared and it will receive an InterruptedException.

If this thread is blocked in an I/O operation upon an InterruptibleChannel then the channel will be closed, the thread's interrupt status will be set, and the thread will receive a ClosedByInterruptException.

If this thread is blocked in a Selector then the thread's interrupt status will be set and it will return immediately from the selection operation, possibly with a non-zero value, just as if the selector's wakeup method were invoked.

If none of the previous conditions hold then this thread's interrupt status will be set.

Interrupting a thread that is not alive need not have any effect.

思考:1s后可以中断线程吗?

请看下面案例:

public class StopThread {

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

        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                int num = 0;
                while (num < Integer.MAX_VALUE)
                {
                    System.out.println(num);
                    num++;
                }
            }
        });
        thread.start();
        // 1s后中断线程
        Thread.sleep(1000);
        thread.interrupt();
    }
}

通过运行该段代码,我们发现1s后线程并没有停止。这也说明,调用 interrupt 方法,并不会影响可中断方法之外的逻辑。线程不会中断,会继续执行。这里的中断概念并不是指中断线程;

思考:对于以上情况,我们要如何停止线程呢?

我们接下来在看这个案例:

public class StopThread {

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

        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                int num = 0;
                while (!Thread.currentThread().isInterrupted() && num < Integer.MAX_VALUE)
                {
                    System.out.println(num);
                    num++;
                }
            }
        });
        thread.start();
        // 1s后中断线程
        Thread.sleep(1000);
        thread.interrupt();
    }
}

我们发现1s后,线程停止了。

中断阻塞方法

public class InterruptSleep {

    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    System.out.println("进入休眠模式");
                    Thread.sleep(10000);
                    System.out.println("休眠结束");
                } catch (InterruptedException e) {
                    System.out.println("我被中断了,提前结束休眠");
                    e.printStackTrace();
                }
            }
        });
        thread.start();
        Thread.sleep(100);
        thread.interrupt();
    }
}

通过以上案例,我们发现,sleep方法会自动响应interrupt方法,从而提前停止线程。

如何在try-catch 停止线程 ?

思考:为什么isInterrupted 无法响应中断呢?
public class CantInterrupt {

    public static void main(String[] args) throws InterruptedException {
        Runnable runnable =() -> {
            int num = 0;
            while (num <= 1000 && !Thread.currentThread().isInterrupted()){
                if (num % 100 == 0) {
                    System.out.println(num + "是100的倍数");
                }
                num++;
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    // 异常被吞了
                    e.printStackTrace();
                }
            }
        };
        Thread thread = new Thread(runnable);
        thread.start();
        Thread.sleep(5000);
        thread.interrupt();
    }
}

这是因为sleep方法会捕获中断的信号,并且会清除掉 interrupted标识,所以isInterrupted方法返回的false

思考:我们要如何才能中断线程呢?
public class TryCatchThread {

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

        new Thread(() -> {
            // 一旦响应中断,则退出程序
            while (Thread.currentThread().isInterrupted()){
                System.out.println("退出程序。。。");
               break;
            };
            TryCatchThread.methods();
        }).start();
        Thread.sleep(10);
        Thread.currentThread().interrupt();
    }

    private static void methods(){
        try {
            Thread.sleep(1000);
            System.out.println("wa!");
        } catch (InterruptedException e) {
            e.printStackTrace();
            // 一旦捕获了异常,首先进行日志保存,其次再次发出中断信号
            Thread.currentThread().interrupt();
        }
    }
}

我们可以采用以上方式停止线程,至于为何要再次中断呢?这是因为sleep方法捕获中断信号后,会清除掉 interrupted标识,所以我们需要再次设置。

上一篇下一篇

猜你喜欢

热点阅读