什么场景会中断状态被设置为true
在Java中,线程的中断状态可以通过调用interrupt()
方法被设置为true
。这个状态的改变通常发生在以下场景:
-
主动请求中断:当一个线程需要被中断时,其他线程或代码块可以主动调用该线程的
interrupt()
方法。例如,你可能有一个长时间运行的任务,当需要停止这个任务时,可以调用其线程的interrupt()
方法。 -
阻塞操作的中断响应:当线程处于阻塞状态(如调用
Thread.sleep()
、Object.wait()
、Thread.join()
等方法)时,如果其他线程调用了该线程的interrupt()
方法,那么阻塞方法会抛出InterruptedException(
当线程在等待期间被中断时,LockSupport.park()
(或其底层机制)会检测到中断状态,并抛出一个InterruptedException)
,当InterruptedException
被抛出时,中断状态会被Java虚拟机(JVM)自动清除。这样,被中断的线程可以在捕获异常后检查中断状态,并据此进行清理工作或退出循环。 -
响应外部事件:在某些情况下,线程可能需要响应外部事件或信号来中断其执行。例如,一个监听用户输入的线程在接收到特定的中断信号时,可能会调用自身的
interrupt()
方法以响应这个信号。 -
协作式中断:在某些复杂的并发场景中,线程可能需要与其他线程协作以决定何时中断。这通常涉及多个线程之间的通信和状态检查,其中某个线程在满足特定条件时可能会调用另一个线程的
interrupt()
方法。
ps:
线程的中断状态在lock()
方法中不会被检查或处理。因此,如果线程在等待锁的过程中被中断,它将继续等待,直到它最终能够获取到锁。中断状态只是被设置,但并不会影响lock()
方法的执行。
如果你希望线程在等待锁的过程中能够响应中断,你应该使用lockInterruptibly()
方法而不是lock()
。lockInterruptibly()
方法在尝试获取锁时,如果线程被中断,会抛出InterruptedException
,从而使线程能够退出等待状态并处理中断。
原理:
要使park
调用响应中断,在Java中,线程的中断是一种协作机制,线程需要自行检查中断状态并响应。对于LockSupport.park(Object blocker)
方法,如果线程在调用park
之后被中断(即其他线程调用了该线程的interrupt()
方法),那么park
方法会检测到中断状态并返回,从而使线程能够继续执行。
因此,你不需要为LockSupport.park(Object blocker)
方法特别配置中断响应。只要线程在调用park
之后被中断,它就会自动唤醒。需要注意的是,park
方法本身不会清除中断状态,所以在唤醒后,如果需要的话,你可能需要手动清除中断状态,通过再次调用Thread.interrupted()
方法来实现。await方法检测到中断后抛出异常,lock方法检测到后继续等待
在Java中,线程中断常用的方法主要有以下几种:
-
使用
Thread
类的interrupt()
方法:
这个方法用于中断线程。当一个线程被中断时,其内部的中断状态会被设置为true
。被中断的线程不会立即停止执行,而是会在检查中断状态后决定是否响应中断。通常,线程会在执行阻塞操作(如sleep()
、wait()
或join()
)或轮询中断状态时响应中断。 -
使用
Thread
类的isInterrupted()
方法:
这个方法用于检查线程是否已经被中断。它不会清除中断状态(即多次调用isInterrupted()
将返回相同的结果,直到线程的中断状态被清除)。 -
使用
Thread
类的interrupted()
方法:
这个方法也用于检查线程是否已经被中断,但与isInterrupted()
不同的是,interrupted()
会清除中断状态(即调用后,线程的中断状态将被设置为false
)。因此,如果连续两次调用interrupted()
,第二次调用将返回false
,除非在两次调用之间线程再次被中断。 -
使用
Lock
接口的lockInterruptibly()
方法:
当使用ReentrantLock
或其他实现了Lock
接口的锁时,可以调用lockInterruptibly()
方法来尝试获取锁。这个方法与lock()
类似,但它在等待锁时能够响应中断。如果线程在等待锁的过程中被中断,lockInterruptibly()
会抛出InterruptedException
。 -
使用
Future
和ExecutorService
的中断处理:
当使用ExecutorService
提交任务并返回一个Future
对象时,可以通过调用Future.cancel(true)
来尝试中断与该Future
关联的任务。这里的true
参数表示如果任务已经开始执行,那么应该尝试中断它。 -
自定义中断处理逻辑:
除了上述方法外,还可以在线程的运行逻辑中自定义中断处理逻辑。例如,可以在循环或长时间运行的任务中定期检查中断状态(通过Thread.isInterrupted()
),并在检测到中断时执行清理工作或退出循环。