首先,看看Thread类里的几个方法:
public static boolean interrupted | 测试当前线程是否已经中断。线程的中断状态 由该方法清除。换句话说,如果连续两次调用该方法,则第二次调用将返回 false(在第一次调用已清除了其中断状态之后,且第二次调用检验完中断状态前,当前线程再次中断的情况除外)。 |
public boolean isInterrupted () |
测试线程是否已经中断。线程的中断状态 不受该方法的影响。 |
public void interrupt () |
中断线程。 |
上面列出了与中断有关的几个方法及其行为,可以看到interrupt是中断线程。如果不了解Java的中断机制,这样的一种解释极容易造成误解,认为调用了线程的interrupt方法就一定会中断线程。
其实,Java的中断是一种协作机制。也就是说调用线程对象的interrupt方法并不一定就中断了正在运行的线程,它只是要求线程自己在合适的时机中断自己。每个线程都有一个boolean的中断状态(不一定就是对象的属性,事实上,该状态也确实不是Thread的字段),interrupt方法仅仅只是将该状态置为true。如下例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
public
class
TestInterrupt {
public
static
void
main(String[] args) {
Thread t =
new
MyThread();
t.start();
t.interrupt();
System.out.println(
"已调用线程的interrupt方法"
);
}
static
class
MyThread
extends
Thread {
public
void
run() {
int
num = longTimeRunningNonInterruptMethod(
2
,
0
);
System.out.println(
"长时间任务运行结束,num="
+ num);
System.out.println(
"线程的中断状态:"
+ Thread.interrupted());
}
private
static
int
longTimeRunningNonInterruptMethod(
int
count,
int
initNum) {
for
(
int
i=
0
; i
for
(
int
j=
0
; j initNum ++;
}
}
return
initNum;
}
}
}
|
一般情况下,会打印如下内容:
已调用线程的interrupt方法
长时间任务运行结束,num=-2
线程的中断状态:true
可见,interrupt方法并不一定能中断线程。但是,如果改成下面的程序,情况会怎样呢?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
import
java.util.concurrent.TimeUnit;
public
class
TestInterrupt {
public
static
void
main(String[] args) {
Thread t =
new
MyThread();
t.start();
t.interrupt();
System.out.println(
"已调用线程的interrupt方法"
);
}
static
class
MyThread
extends
Thread {
public
void
run() {
int
num = -
1
;
try
{
num = longTimeRunningInterruptMethod(
2
,
0
);
}
catch
(InterruptedException e) {
System.out.println(
"线程被中断"
);
throw
new
RuntimeException(e);
}
System.out.println(
"长时间任务运行结束,num="
+ num);
System.out.println(
"线程的中断状态:"
+ Thread.interrupted());
}
private
static
int
longTimeRunningInterruptMethod(
int
count,
int
initNum)
throws
InterruptedException{
for
(
int
i=
0
; i TimeUnit.SECONDS.sleep(
5
);
}
return
initNum;
}
}
}
|
经运行可以发现,程序抛出异常停止了,run方法里的后两条打印语句没有执行。那么,区别在哪里?
一般说来,如果一个方法声明抛出InterruptedException,表示该方法是可中断的(没有在方法中处理中断却也声明抛出InterruptedException的除外),也就是说可中断方法会对interrupt调用做出响应(例如sleep响应interrupt的操作包括清除中断状态,抛出InterruptedException),如果interrupt调用是在可中断方法之前调用,可中断方法一定会处理中断,像上面的例子,interrupt方法极可能在run未进入sleep的时候就调用了,但sleep检测到中断,就是处理该中断。如果在可中断方法正在执行中的时候调用interrupt,会怎么样呢?这就要看可中断方法处理中断的时机了,只要可中断方法能检测到中断状态为true,就应该处理中断。让我们为开头的那段代码加上中断处理。
那么自定义的可中断方法该如何处理中断呢?那就是在适合处理中断的地方检测线程中断状态并处理。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
public
class
TestInterrupt {
public
static
void
main(String[] args)
throws
Exception {
Thread t =
new
MyThread();
t.start();
// TimeUnit.SECONDS.sleep(1);//如果不能看到处理过程中被中断的情形,可以启用这句再看看效果
t.interrupt();
System.out.println(
"已调用线程的interrupt方法"
);
}
static
class
MyThread
extends
Thread {
public
void
run() {
int
num;
try
{
num = longTimeRunningNonInterruptMethod(
2
,
0
);
}
catch
(InterruptedException e) {
throw
new
RuntimeException(e);
}
System.out.println(
"长时间任务运行结束,num="
+ num);
System.out.println(
"线程的中断状态:"
+ Thread.interrupted());
}
private
static
int
longTimeRunningNonInterruptMethod(
int
count,
int
initNum)
throws
InterruptedException {
if
(interrupted()) {
throw
new
InterruptedException(
"正式处理前线程已经被请求中断"
);
}
for
(
int
i=
0
; i
for
(
int
j=
0
; j initNum ++;
}
//假如这就是一个合适的地方
if
(interrupted()) {
//回滚数据,清理操作等
throw
new
InterruptedException(
"线程正在处理过程中被中断"
);
}
}
return
initNum;
}
}
}
|
如上面的代码,方法longTimeRunningNonInterruptMethod此时已是一个可中断的方法了。在进入方法的时候判断是否被请求中断,如果是,就不进行相应的处理了;处理过程中,可能也有合适的地方处理中断,例如上面最内层循环结束后。
这段代码中检测中断用了Thread的静态方法interrupted,它将中断状态置为false,并将之前的状态返回,而isInterrupted只是检测中断,并不改变中断状态。一般来说,处理过了中断请求,应该将其状态置为false。但具体还要看实际情形。
相关推荐
Java锁机制是多线程编程中的关键组成部分,用于控制对共享资源的访问,确保并发环境下的数据一致性。本文将深入探讨Java锁机制,并基于提供的"面向Java锁机制的字节码自动重构框架"来讨论其背后的原理和应用。 在...
在Java多线程编程中,中断机制是一种优雅的线程停止策略,相比已废弃的`stop()`方法,中断机制提供了更安全、可控的方式来结束线程的执行。本文将深入探讨`stop()`, `interrupted()`以及`isInterrupted()`这三个方法...
通过以上分析可以看出,Java的异常处理机制十分强大且灵活,能够帮助开发者更好地控制程序的执行流程,提高程序的健壮性和稳定性。然而,这也意味着开发者需要对异常处理有深刻的理解才能充分利用这一机制的优势。
内容概要:本文深入探讨了Java中的并发控制机制,重点讲解了ReentrantLock和synchronized的特点及其背后的实现原理。通过对两者的特性进行对比,详细解析了ReentrantLock在灵活性、公平性和中断响应等方面的优点。并...
《Java常见错误分析20例》是一本专为Java开发者准备的电子书,它深入剖析了在编程过程中可能遇到的20种典型错误,并提供了详尽的解决方案。这本书旨在帮助初学者和经验丰富的程序员更好地理解和解决Java编程中的问题...
### Java异常机制深入研究 #### 一、Java异常概述与分类 Java中的异常处理机制是其强大特性之一,它能够帮助开发者有效地管理程序运行时出现的错误情况,从而提高程序的健壮性和可维护性。Java中的异常主要分为三...
"java并发源码分析之实战编程"这个主题深入探讨了Java平台上的并发处理机制,旨在帮助开发者理解并有效地利用这些机制来提高程序性能和可扩展性。在这个专题中,我们将围绕Java并发库、线程管理、锁机制、并发容器...
在Java中,异常是一种在程序执行过程中发生的事件,它中断了正常的程序流程。异常类是Java异常处理的基础,它们构成了一个层次结构,从根类`Throwable`开始,包括`Error`和`Exception`两个主要分支。`Error`通常表示...
- **Thread Local Handshakes**: 提供了一种新的线程中断机制,可以在不抛出InterruptedException的情况下中断线程。 - **ZGC: Zero Latency Garbage Collector**: 一个实验性的低延迟垃圾收集器,适用于大内存...
“通过反射机制得到类的实例”是Java的一个强大特性。反射允许程序在运行时动态地获取类的信息并操作其成员。例如,你可以使用反射创建对象,调用方法,访问私有属性等。这在数据采集分析中可能用于动态加载或调用...
- **Java并发机制**:Java提供了丰富的并发机制来支持多线程程序的编写,包括但不限于`Thread`类、`Runnable`接口、`Callable`接口以及`Executor`框架等。 - **锁机制**:Java中的锁机制主要包括synchronized关键字...
"Java异常处理机制分析与研究" 在Java编程中,错误是无法避免的,但通过使用Java的异常处理机制,我们可以控制和处理异常的出现,从而保证程序的安全性和可用性。下面我们将分析Java异常处理机制,并讨论如何运用它...
2. **线程管理**:讨论如何创建、启动、停止和控制线程,包括线程池的使用,如`ExecutorService`和`ThreadPoolExecutor`,以及线程的优先级和中断机制。 3. **并发控制**:讲解Java中的同步机制,如`synchronized`...
4. 状态记录和日志管理:详细记录系统的运行状态和错误信息,便于事后分析故障原因,优化策略,并预防类似问题再次发生。 5. 自愈能力:通过自动化手段,系统能够自我诊断并修复问题,无需人工干预。例如,自动扩展...
4. **JavaCV(Java Computer Vision)**:这是OpenCV库的Java接口,提供了计算机视觉的便利工具,包括图像处理、视频分析等功能。在这个项目中,JavaCV可能用于处理FFmpeg输出的视频帧,以便于在网页上展示或进行...
自JDK 5.0起,引入了更高级的并发控制机制,如`java.util.concurrent.locks.ReentrantLock`,提供可中断的等待和公平锁等特性,比传统的`synchronized`关键字提供了更多的灵活性和控制。 **第3章 案例分析** 3.1 ...
8. **异常处理**:在与硬件交互时,可能会遇到网络中断、设备未响应等异常情况,因此良好的异常处理机制可以确保程序的健壮性。 9. **日志记录**:为了调试和故障排查,应记录程序运行中的关键信息,Java的log4j或...