什么是线程中断?

本文详细介绍了Java线程中断的概念,包括中断不是强制停止线程,而是发送中断信号。通过四个示例展示了如何使用Thread.interrupt()、isInterrupted()和interrupted()方法进行线程中断,并解释了为何在sleep()方法中需要重新设置中断标志。强调了正确响应中断信号的重要性,以及避免使用已废弃的线程停止方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

下面的这断代码大家应该再熟悉不过了,线程休眠需要捕获或者抛出线程中断异常,也就是你在睡觉的时候突然有个人冲进来把你吵醒了。

try {
	Thread.sleep(3000);
} catch (InterruptedException e) {
	e.printStackTrace();
}

此时线程被打断后,代码会继续运行或者抛出异常结束运行,这并不是我们需要的中断线程的作用。

到底是什么是线程中断?

线程中断即线程运行过程中被其他线程给打断了,它与 stop 最大的区别是:stop 是由系统强制终止线程,而线程中断则是给目标线程发送一个中断信号,如果目标线程没有接收线程中断的信号并结束线程,线程则不会终止,具体是否退出或者执行其他逻辑由目标线程决定。

我们来看下线程中断最重要的 3 个方法,它们都是来自 Thread 类!

1、java.lang.Thread#interrupt

中断目标线程,给目标线程发一个中断信号,线程被打上中断标记。

2、java.lang.Thread#isInterrupted()

判断目标线程是否被中断,不会清除中断标记。

3、java.lang.Thread#interrupted

判断目标线程是否被中断,会清除中断标记。

线程中断实战

我们来实例演示下线程中断如何用!

示例1(中断失败)

/**
 * 来源:Java技术栈
 */
private static void test1() {
	Thread thread = new Thread(() -> {
		while (true) {
			Thread.yield();
		}
	});
	thread.start();
	thread.interrupt();
}

请问示例1中的线程会被中断吗?答案:不会,因为虽然给线程发出了中断信号,但程序中并没有响应中断信号的逻辑,所以程序不会有任何反应。

示例2:(中断成功)

/**
 * 来源:Java技术栈
 */
private static void test2() {
	Thread thread = new Thread(() -> {
		while (true) {
			Thread.yield();

			// 响应中断
			if (Thread.currentThread().isInterrupted()) {
				System.out.println("Java技术栈线程被中断,程序退出。");
				return;
			}
		}
	});
	thread.start();
	thread.interrupt();
}

我们给示例2加上了响应中断的逻辑,程序接收到中断信号打印出信息后返回退出。

示例3(中断失败)

/**
 * 来源:Java技术栈
 */
private static void test3() throws InterruptedException {
	Thread thread = new Thread(() -> {
		while (true) {
			// 响应中断
			if (Thread.currentThread().isInterrupted()) {
				System.out.println("Java技术栈线程被中断,程序退出。");
				return;
			}

			try {
				Thread.sleep(3000);
			} catch (InterruptedException e) {
				System.out.println("Java技术栈线程休眠被中断,程序退出。");
			}
		}
	});
	thread.start();
	Thread.sleep(2000);
	thread.interrupt();
}

示例3 sleep() 方法被中断,并输出了 Java技术栈线程休眠被中断,程序退出。 程序继续运行……为什么呢?

来看 sleep 的源码:

可以看出 sleep() 方法被中断后会清除中断标记,所以循环会继续运行。。

示例4(中断成功)

/**
 * :Java技术栈
 */
private static void test4() throws InterruptedException {
	Thread thread = new Thread(() -> {
		while (true) {
			// 响应中断
			if (Thread.currentThread().isInterrupted()) {
				System.out.println("Java技术栈线程被中断,程序退出。");
				return;
			}

			try {
				Thread.sleep(3000);
			} catch (InterruptedException e) {
				System.out.println("Java技术栈线程休眠被中断,程序退出。");
				Thread.currentThread().interrupt();
			}
		}
	});
	thread.start();
	Thread.sleep(2000);
	thread.interrupt();
}

示例4全部信息输出并正常退出,只是在 sleep() 方法被中断并清除标记后手动重新中断当前线程,然后程序接收中断信号返回退出。

通过以上 4 个中断示例,相信对 Java 线程中断的概念有了全面的了解。更多 Java 多线程技术文章请关注Java技术栈。


 

首先,一个线程不应该由其他线程来强制中断或停止,而是应该由线程自己自行停止。
所以,Thread.stop, Thread.suspend, Thread.resume 都已经被废弃了。
而 Thread.interrupt 的作用其实也不是中断线程,而是「通知线程应该中断了」,
具体到底中断还是继续运行,应该由被通知的线程自己处理。

具体来说,当对一个线程,调用 interrupt() 时,

  1. 如果线程处于被阻塞状态(例如处于sleep, wait, join 等状态),那么线程将立即退出被阻塞状态,并抛出一个InterruptedException异常。仅此而已。在线程被同步锁所阻塞时,调用interrupt线程无法去检查中断状态或者抛出InterruptedException
  2. 如果线程处于正常活动状态,那么会将该线程的中断标志设置为 true,仅此而已。被设置中断标志的线程将继续正常运行,不受影响。

interrupt() 并不能真正的中断线程,需要被调用的线程自己进行配合才行。
也就是说,一个线程如果有被中断的需求,那么就可以这样做。

  1. 在正常运行任务时,经常检查本线程的中断标志位,如果被设置了中断标志就自行停止线程。
  2. 在调用阻塞方法时正确处理InterruptedException异常。(例如,catch异常后就结束线程。)
Thread thread = new Thread(() -> {
    while (!Thread.interrupted()) {
        // do more work.
    }
});
thread.start();

// 一段时间以后
thread.interrupt();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值