Java多线程详解!线程的中断方法interrupt()和终止线程的使用分析

这是我参与11月更文挑战的第20天,活动详情查看:2021最后一次更文挑战

线程中断interrupt

  • interrupt() 的作用是中断当前线程
    • 当前线程可以中断本身运行的线程,如果其余线程调用本线程的interrupt() 方法时,会通过checkAccess() 检查权限,会抛出SecurityException异常
    • 如果本线程因为调用线程的wait() 方法 ,wait(long) 或者wait(long, int), 或者是调用了线程的join(), join(long),join(long, int),sleep(long),sleep(long, int) 进入阻塞状态时,调用interrupt() 方法,那么该线程的 [中断状态] 就会被清除并且会收到一个InterruptedException异常
    • 如果线程阻塞在一个Selector选择器中,那么通过interrupt() 中断时,线程的中断标记会被设置为true, 并且会立即从选择操作中返回
  • 通过interrupt() 中断线程时,中断标记会被设置为true, 中断一个 [已经终止的线程] 不会产生任何操作

终止线程

阻塞状态

  • 一般情况下,通过中断interrupt方式终止处于 [阻塞状态] 的线程
    • 当前线程通过调用sleep(),wait(),join() 等方法进入阻塞状态,若此时调用线程的interrupt() 方法可以将线程的中断标记设置为true
    • 由于处于阻塞状态,中断标记会被清除,同时产生一个InterruptedException异常
    • InterruptedException异常放在适当的位置就能终止线程
@Override
public void run() {
	try {
		while (true) {
			// 运行线程
		}
	} catch (InterruptedException e) {
		// 捕获到产生的InterruptedException异常,退出while(true)循环,线程终止
	}
}
复制代码
  • while(true) 中不断执行任务,当线程处于阻塞状态时,调用线程的interrupt() 产生InterruptedException异常,中断的异常在while(true) 之外捕获,这样就可以退出while循环,终止异常
  • InterruptedException的捕获一般放在while(true) 循环体外,这样就可以在产生异常时退出while(true) 循环.如果对InterruptedException的捕获放置在while(true) 循环体之内,就需要添加额外的退出处理

运行状态

  • 一般情况下,通过 [标记] 终止处于 [运行状态] 的线程
  • 标记包括: 中断标记额外添加标记

中断标记

@Override
public void run() {
	while (!isInterrupted) {
		// 运行线程
	}
}
复制代码
  • isInterrupted() 方法用于判断线程的中断标记是否为true:
    • 当线程处于运行状态,并且需要终止时,可以调用线程的interrupt() 方法,将线程的中断标记设置为true. 此时isInterrupted() 会返回true, 此时就会退出while循环
  • interrupt() 并不会终止处于 [运行状态] 的线程,只是将线程的中断标记设置为true

额外添加标记

private volatile boolean flag = true;

protected void stopTask() {
	flag = false;
}

@Override
public void run() {
	while (flag) {
		// 运行任务
	}
}
复制代码
  • 线程中有一个flag标记,默认值为true
  • 可以通过stopTask() 方法来设置flag标记,当需要终止该方法时,调用该线程的stopTask() 方法就可以让线程退出循环
  • 使用volatile定义flag类型: 保证flag的可见性.即其余线程通过调用stopTask() 方法修改了flag的值之后,本线程可以看到修改后flag的值

综合状态线程

  • 综合状态线程: 处于阻塞状态和运行状态的线程
  • 综合状态线程的通用终止方式:
@Override
public void run() {
	try {
		// isInterrupted保证只要中断标记为true就终止线程
		while (!isInterrupted()) {
			// 运行线程
		}
	} catch (InterruptedException e) {
		// InterruptedException保证只要当InterruptedException异常产生时就终止线程
	}
}
复制代码

interrupted()和isInterrupted()异同

  • 相同点: interrupted()isInterrupted() 都能够用于检测对象的 [中断标记]
  • 不同点:
    • interrupted() 除了返回 [中断标记] 之外,还会清除 [中断标记], 即将 [中断标记] 设置为false
    • isInterrupted() 仅仅返回 [中断标记]

猜你喜欢

转载自juejin.im/post/7033349132785827848