栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

JDK Thread interrupt 中断

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

JDK Thread interrupt 中断

博文目录

文章目录
  • 线程中断
  • 中断说明
  • 代码验证
  • 使用


JDK Thread join

线程中断

通过 stop 来终止线程太过粗鲁, 且不安全, 可能有某些资源没有关闭, 锁没有释放等造成问题

通过 interrupt 给线程设置中断标记, 是否响应中断, 由线程自己来决定, 可以更温和地在线程安全点终止线程

可以通过线程中断标记, 在一定程度上做到线程通信

中断说明

thread.interrupt(), 给指定线程设置中断标记
thread.isInterrupted(), 获取指定线程的中断标记
Thread.interrupted(), 获取指定线程的中断标记, 且有标记则清除

如果线程执行 Object.wait() / Thread.sleep() / Thread.join() 前被设置了中断标记, 则执行到这些代码时, 不会睡眠或阻塞, 直接抛出中断异常, 并清除中断标记

如果线程正在执行 Object.wait() / Thread.sleep() / Thread.join() 中时被设置了中断标记, 则直接唤醒线程, 抛出中断异常, 并清除中断标记

代码验证
@Test
@SneakyThrows
public void test() {

    // thread.isInterrupted(), 获取中断标记
    // thread.interrupt(), 设置中断标记, 但不会改变线程的运行状态
    // Thread.interrupted(), 获取中断标记, 有则清除
    // Thread.sleep(), 分两种情况, 1.线程sleep前被设置中断,执行到sleep时,不睡,直接抛出中断异常,并清除中断标记, 2.线程sleep中被设置中断,直接唤醒线程,抛出中断异常,并清除中断标记
    // object.wait(), 分两种情况, 1.线程wait前被设置中断,执行到wait时,不阻塞,直接抛出中断异常,并清除中断标记, 2.线程wait中被设置中断,直接唤醒线程,抛出中断异常,并清除中断标记
    // Thread.join(), 分两种情况, 1.线程join前被设置中断,执行到join时,不阻塞,直接抛出中断异常,并清除中断标记(本质上是wait), 2.线程join中被设置中断,直接唤醒线程,抛出中断异常,并清除中断标记(本质上是wait)

    Thread thread = new Thread(() -> {
        Thread me = Thread.currentThread();

        log.info("默认是没有中断标记的: {}", me.isInterrupted());


        System.out.println();
        // 给线程设置中断标记
        me.interrupt();
        log.info("设置中断标记后: {}", me.isInterrupted());


        System.out.println();
        // 设置中断标记
        me.interrupt();
        // 获取线程中断标记, 会清除中断标记
        // 内部是 Thread.currentThread().isInterrupted(true);
        log.info("调用 Thread.interrupted() 返回的值: {}", Thread.interrupted());
        log.info("调用 Thread.interrupted() 会清除中断标记: {}", me.isInterrupted());
        // 清除中断标记
        Thread.interrupted();


        System.out.println();
        // 设置中断标记
        me.interrupt();
        // 主动抛出中断异常, 是不会清除线程的中断标记的
        try {
            throw new InterruptedException();
        } catch (InterruptedException e) {
            log.info("主动抛出中断异常, 不会清除中断标记: {}", me.isInterrupted());
        }
        // 清除中断标记
        Thread.interrupted();


        System.out.println();
        // 设置中断标记
        me.interrupt();
        // 线程sleep前被设置中断,执行到sleep时,不睡,直接抛出中断异常,并清除中断标记
        try {
            log.info("子线程开始 sleep:10 秒");
            // 本质上调用的是 Thread.sleep()
            TimeUnit.SECONDS.sleep(10);
        } catch (InterruptedException e) {
            log.info("线程sleep前被设置中断,执行到sleep时,不睡,直接抛出中断异常,并清除中断标记: {}", me.isInterrupted());
        }
        // 清除中断标记
        Thread.interrupted();


        System.out.println();
        // 线程sleep中被设置中断,直接唤醒线程,抛出中断异常,并清除中断标记
        try {
            log.info("子线程开始 sleep:10 秒");
            // 本质上调用的是 Thread.sleep()
            TimeUnit.SECONDS.sleep(10);
        } catch (InterruptedException e) {
            log.info("线程sleep中被设置中断,直接唤醒线程,抛出中断异常,并清除中断标记: {}", me.isInterrupted());
        }
        // 清除中断标记
        Thread.interrupted();


        System.out.println();
        // 设置中断标记
        me.interrupt();
        // 线程wait前被设置中断,执行到wait时,不阻塞,直接抛出中断异常,并清除中断标记
        synchronized (this) {
            try {
                log.info("子线程开始 wait:10 秒");
                wait(1000 *10);
            } catch (InterruptedException e) {
                log.info("线程wait前被设置中断,执行到wait时,不阻塞,直接抛出中断异常,并清除中断标记: {}", me.isInterrupted());
            }
        }
        // 清除中断标记
        Thread.interrupted();


        System.out.println();
        // 线程wait前被设置中断,执行到wait时,不阻塞,直接抛出中断异常,并清除中断标记
        synchronized (this) {
            try {
                log.info("子线程开始 wait:10 秒");
                wait(1000 *10);
            } catch (InterruptedException e) {
                log.info("线程wait中被设置中断,直接唤醒线程,抛出中断异常,并清除中断标记: {}", me.isInterrupted());
            }
        }
        // 清除中断标记
        Thread.interrupted();


        System.out.println();
        // 子线程里再开一个需要执行10秒的新子线程
        Thread other = new Thread(() -> {
            try {
                TimeUnit.SECONDS.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        // 启动该新子线程
        other.start();
        // 设置中断标记
        me.interrupt();
        // 线程join前被设置中断,执行到join时,不阻塞,直接抛出中断异常,并清除中断标记(本质上是wait)
        try {
            // 让子线程me等待子线程other之行结束
            log.info("子线程开始 join:10 秒");
            other.join(1000 * 10);
        } catch (InterruptedException e) {
            log.info("线程join前被设置中断,执行到join时,不阻塞,直接抛出中断异常,并清除中断标记(本质上是wait): {}", me.isInterrupted());
        }
        // 清除中断标记
        Thread.interrupted();


        System.out.println();
        // 线程join中被设置中断,直接唤醒线程,抛出中断异常,并清除中断标记(本质上是wait)
        try {
            // 让子线程me等待子线程other之行结束
            log.info("子线程开始 join:10 秒");
            other.join(1000 * 10);
        } catch (InterruptedException e) {
            log.info("线程join中被设置中断,直接唤醒线程,抛出中断异常,并清除中断标记(本质上是wait): {}", me.isInterrupted());
        }
        // 清除中断标记
        Thread.interrupted();


        System.out.println();
        log.info("子线程结束");
        System.out.println();
    });
    thread.start();

    TimeUnit.SECONDS.sleep(1);
    log.info("主线程睡1秒后给子线程设置中断标记, 测试sleep中被设置中断");
    thread.interrupt();

    TimeUnit.SECONDS.sleep(1);
    log.info("主线程再睡1秒后给子线程设置中断标记, 测试wait中被设置中断");
    thread.interrupt();

    TimeUnit.SECONDS.sleep(1);
    log.info("主线程再睡1秒后给子线程设置中断标记, 测试join中被设置中断");
    thread.interrupt();

    TimeUnit.SECONDS.sleep(1);
    log.info("主线程再睡1秒等待子线程测试完成");

    log.info("主线程结束");

}
[20220518.173753.647][INFO ][Thread-1] 默认是没有中断标记的: false

[20220518.173753.650][INFO ][Thread-1] 设置中断标记后: true

[20220518.173753.650][INFO ][Thread-1] 调用 Thread.interrupted() 返回的值: true
[20220518.173753.650][INFO ][Thread-1] 调用 Thread.interrupted() 会清除中断标记: false

[20220518.173753.650][INFO ][Thread-1] 主动抛出中断异常, 不会清除中断标记: true

[20220518.173753.651][INFO ][Thread-1] 子线程开始 sleep:10 秒
[20220518.173753.651][INFO ][Thread-1] 线程sleep前被设置中断,执行到sleep时,不睡,直接抛出中断异常,并清除中断标记: false

[20220518.173753.651][INFO ][Thread-1] 子线程开始 sleep:10 秒
[20220518.173754.652][INFO ][main] 主线程睡1秒后给子线程设置中断标记, 测试sleep中被设置中断
[20220518.173754.652][INFO ][Thread-1] 线程sleep中被设置中断,直接唤醒线程,抛出中断异常,并清除中断标记: false

[20220518.173754.652][INFO ][Thread-1] 子线程开始 wait:10 秒
[20220518.173754.652][INFO ][Thread-1] 线程wait前被设置中断,执行到wait时,不阻塞,直接抛出中断异常,并清除中断标记: false

[20220518.173754.652][INFO ][Thread-1] 子线程开始 wait:10 秒
[20220518.173755.656][INFO ][main] 主线程再睡1秒后给子线程设置中断标记, 测试wait中被设置中断
[20220518.173755.656][INFO ][Thread-1] 线程wait中被设置中断,直接唤醒线程,抛出中断异常,并清除中断标记: false

[20220518.173755.656][INFO ][Thread-1] 子线程开始 join:10 秒
[20220518.173755.656][INFO ][Thread-1] 线程join前被设置中断,执行到join时,不阻塞,直接抛出中断异常,并清除中断标记(本质上是wait): false

[20220518.173755.656][INFO ][Thread-1] 子线程开始 join:10 秒
[20220518.173756.668][INFO ][main] 主线程再睡1秒后给子线程设置中断标记, 测试join中被设置中断
[20220518.173756.668][INFO ][Thread-1] 线程join中被设置中断,直接唤醒线程,抛出中断异常,并清除中断标记(本质上是wait): false

[20220518.173756.668][INFO ][Thread-1] 子线程结束

[20220518.173757.682][INFO ][main] 主线程再睡1秒等待子线程测试完成
[20220518.173757.682][INFO ][main] 主线程结束
使用
@Test
@SneakyThrows
public void demo() {
	Thread thread = new Thread(() -> {
		while (!Thread.interrupted()) {
			try {
				log.info("开始做某事");
				Thread.sleep(600);
				log.info("结束做某事");
			} catch (InterruptedException e) {
				e.printStackTrace();
				log.info("中断异常, 清理资源");
				// 如果在sleep/wait/join时被设置中断, 中断标记会被清除
				// 针对该循环中的中断异常, 需要自己补充一下中断标记, 不然循环不会退出, 这里可以注释下来看运行效果
				Thread.currentThread().interrupt();
			}
		}
	});
	thread.start();

	TimeUnit.SECONDS.sleep(1);
	thread.interrupt();
	// 主线程终止的话, 子线程也会跟着终止, 所以让主线程多运行下, 方便看到 中断异常没有导致线程终止 的效果
	TimeUnit.SECONDS.sleep(1);
}
[20220518.181000.744][INFO ][Thread-1] 开始做某事
[20220518.181001.357][INFO ][Thread-1] 结束做某事
[20220518.181001.357][INFO ][Thread-1] 开始做某事
java.lang.InterruptedException: sleep interrupted
	at java.lang.Thread.sleep(Native Method)
	at jdk.java.lang.ThreadInterruptTest.lambda$demo$2(ThreadInterruptTest.java:187)
	at java.lang.Thread.run(Thread.java:748)
[20220518.181001.749][INFO ][Thread-1] 中断异常, 清理资源
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/915461.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号