2.你中断线程的方式用对了么?

2.你中断线程的方式用对了么?,第1张

2.你中断线程的方式用对了么? 启动线程

线程在初始化完成之后,调用start方法就可以启动线程,

什么是中断

中断是作为线程的一个标志位,表示运行中的线程是否被其它线程做了中断 *** 作。中断的意思是其他线程对本线程调用interrupt方法,使其标志位变成中断。
线程自身通过检查中断标志位是否为true(通过调用isInterrupted()来进行判断),如果为true,则说明已经被其他线程做了中断 *** 作。
如果有的方法抛出了(InterruptedException),则会在抛出此异常之前,将中断标志进行清除(Thread.interrupted()),如(sleep方法)所以这个时候你如果调用isInterrupted()方法,将会返回false。
我们可以通过一段代码进行演示:

package com.ams.thread.lesson2;

import cn.hutool.core.thread.ThreadUtil;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.TimeUnit;


@Slf4j
public class Example7 {

    public static void main(String[] args) {
        Thread sleepThread = new Thread(new SleepThread());
        Thread busyThread = new Thread(new BusyThread());   
        sleepThread.start();
        busyThread.start();
        ThreadUtil.sleep(3000);
        sleepThread.interrupt();
        busyThread.interrupt();
        log.info("sleepThread isInterrupted {}",sleepThread.isInterrupted());
        log.info("busyThread isInterrupted {}",busyThread.isInterrupted());
    }

    static class SleepThread implements Runnable {
        @Override
        public void run() {
           while (true){
               ThreadUtil.sleep(5000);
           }
        }
    }

    static class BusyThread implements Runnable {
        @Override
        public void run() {
           while (true){

           }
        }
    }
}

通过输出结果可以看到,sleep在抛出中断异常之前,将标志位清除了;
sleep源码是打不开的,声明了native,使用c++实现的。

这些方法已经不建议用了

中断或暂停线程的方法包括:suspend()、resume()、stop().
大家在使用这些方法去停止线程时,发现已经被标注成弃用了,为什么会被启用呢?
原因是由于调用这些方法停止线程后,线程本身所占用的资源(如suspend 不会释放锁)并不会被释放,导致资源一直不能被其它线程使用,我们可以通过下面这段代码验证下:

package com.ams.thread.lesson2;

import cn.hutool.core.thread.ThreadUtil;
import lombok.extern.slf4j.Slf4j;


@Slf4j
public class Example8 {

    public static void main(String[] args) {
        Thread suspendThread = new Thread(new SuspendThread());
        Thread normalThread = new Thread(new NormalThread());
        suspendThread.start();
        ThreadUtil.sleep(5000);
        normalThread.start();
        suspendThread.suspend();
        log.info("suspendThread isInterrupted");
    }

    static class SuspendThread implements Runnable {
        @Override
        public void run() {
            synchronized (Example8.class){
                while (true){
                    ThreadUtil.sleep(2000);
                    log.info("SuspendThread running");
                }
            }
        }
    }
    static class NormalThread implements Runnable {
        @Override
        public void run() {
            synchronized (Example8.class){
                log.info("NormalThread 获取锁");
            }
        }
    }
}

通过输出就够可以看到:我在调用线程的suspend()方法后,SuspendThread并没有继续打印,但是NormalThread线程却一直打印没有获得锁的日志。

那么问题就来了:如果这些终止线程的方法,都不可用,那么我怎么能优雅的终止一个线程呢?

优雅的终止线程

可以通过两种方式:

  • 通过中断标志位进行判断是否终止异常,A线程想停止B线程,则调用B线程的interrupt()方法,B线程通过在运行过程中判断中断标志位是否为true来决定是否终止线程
  • 自定义一个变量,通过外界对此变量的 *** 作,使线程进行终止
package com.ams.thread.lesson2;

import cn.hutool.core.thread.ThreadUtil;
import lombok.extern.slf4j.Slf4j;


@Slf4j
public class Example9 {

    public static void main(String[] args) {
        BeautifulStopThread run = new BeautifulStopThread();
        Thread beautifulStopThread = new Thread(run);
        beautifulStopThread.start();
        ThreadUtil.sleep(5000);
//        run.stop();
        beautifulStopThread.interrupt();

    }
    static class BeautifulStopThread implements Runnable {
        boolean boolStop = false;
        @Override
        public void run() {
            synchronized (Example9.class) {
                while (!boolStop && !Thread.currentThread().isInterrupted()) {
                    log.info("BeautifulStopThread running");
                }
                log.info("BeautifulStopThread stop");
            }
        }
        public void stop() {
            this.boolStop = true;
        }
    }
}

通过结果可以看出 stop方法和interrupt方法都可以使线程优雅的停止。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5686254.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存