Java多线程之中断线程(Interrupt)的使用详解
在Java中,线程采用协作式多任务处理,即线程必须自主地停止自己或按照其他线程的意愿停止。中断线程是线程之间传递信号的一种机制,允许一个线程打断另一个线程的执行。本文将详细讲解Java多线程之中断线程的使用方法。
中断线程的基本原理以及使用方式
中断线程的本质是给目标线程发出一个中断信号,该信号会将目标线程从运行状态转换为阻塞状态,从而让目标线程有机会退出。在Java中,要中断一个线程,可以使用Thread类提供的interrupt()方法,即向目标线程发出中断信号。
下面是中断线程的基本使用方法,注意,当你调用targetThread.interrupt()方法时,targetThread事实上并没有立即中断,而是抛出了一个中断异常。因此,目标线程在捕获到中断异常后,可以采取一些措施使得线程中止。
public class InterruptThreadDemo {
public static void main(String[] args) throws InterruptedException {
Thread thread = new MyThread();
thread.start();
Thread.sleep(100);
thread.interrupt(); // 中断线程
}
static class MyThread extends Thread {
@Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
System.out.println("Running");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// 捕获到中断异常,线程中止
Thread.currentThread().interrupt();
}
}
}
}
}
上面的示例在MyThread的run()方法中,不断地输出“Running”,如果线程中断,则会抛出InterruptedException异常,中断那个循环,从而使得线程中止。注意,在捕获InterruptedException异常之后,我们必须再次设置线程的中断状态,否则线程仍然会保持“不中断”的状态。
给阻塞的线程发出中断信号
在上面的示例中,我们可以看到,如果线程不具备阻塞特性,那么中断线程的方法是非常简单的。但是,如果线程正在等待锁、等待输入/输出、或者阻塞在某个方法上,那么就需要注意中断的处理方式。
在Java中,许多线程是阻塞线程,如等待I/O操作完成时的线程、等待锁的线程等等,这些线程此时都阻塞了下来,只有特定的事件才能使得线程释放自己的阻塞状态。因此,如果线程正在等待阻塞事件发生,那就需要给线程发送一个中断信号,让线程提前退出等待状态。
比如,下面的示例中,我们启动了两个线程,在其中一个线程中,我们让它去获取一个锁,然后就一直持有该锁,从而造成另一个线程等待锁的状态。然后在main线程中中断等待锁的线程,从而让其提前返回,并释放锁。需要注意的是,中断等待线程就像是调用了Object.wait()方法一样,它会放弃线程占用的锁,因此在等待线程中,我们需要检验共享变量flag的状态,以免造成数据错误。
public class InterruptThreadDemo2 {
public static void main(String[] args) throws InterruptedException {
final Object lock = new Object();
Thread waitingThread = new Thread(() -> {
System.out.println("Waiting for lock");
synchronized (lock) {
while (!Thread.currentThread().isInterrupted()) {
try {
lock.wait();
} catch (InterruptedException e) {
System.out.println("Thread is interrupted, will exit");
Thread.currentThread().interrupt(); // 继续下一次的循环检查
}
}
System.out.println("Lock has been released");
}
});
Thread runningThread = new Thread(() -> {
System.out.println("I'm running");
LockSupport.park(); // 阻塞线程
});
waitingThread.start();
runningThread.start();
Thread.sleep(100);
waitingThread.interrupt(); // 中断等待线程,并释放锁
waitingThread.join();
runningThread.join();
}
}
上面的示例中,我们的等待线程通过wait()方法,持续等待一个锁的释放。而另一个运行线程则直接采用park()方法,阻塞自己。然后在main线程中,我们打算中断等待线程,并释放锁。当线程被中断时,就会抛出中断异常,并结束循环。线程中止后,我们需要手动将线程的中断状态再次设置为true,以便后续的判断。
总结
中断线程是Java中实现多线程协作的一种非常直观的方式。当需要一方停止另一方执行,或者需要让线程在等待状态中提前返回时,中断线程都是一种非常有效的方式。但需要注意,中断线程不会直接让线程停止运行,而是通过抛出中断异常,让线程有机会正确结束。在实际应用中,我们需要注意对阻塞线程的处理方式,以免造成死锁或数据错误。
至此,本文中断线程的使用方法已经讲解完毕。希望本文能对大家理解Java多线程协作提供帮助。
完整的代码示例与运行结果如下:
// InterruptThreadDemo.java
public class InterruptThreadDemo {
public static void main(String[] args) throws InterruptedException {
Thread thread = new MyThread();
thread.start();
Thread.sleep(100);
thread.interrupt(); // 中断线程
}
static class MyThread extends Thread {
@Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
System.out.println("Running");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// 捕获到中断异常,线程中止
Thread.currentThread().interrupt();
}
}
}
}
}
// InterruptThreadDemo2.java
public class InterruptThreadDemo2 {
public static void main(String[] args) throws InterruptedException {
final Object lock = new Object();
Thread waitingThread = new Thread(() -> {
System.out.println("Waiting for lock");
synchronized (lock) {
while (!Thread.currentThread().isInterrupted()) {
try {
lock.wait();
} catch (InterruptedException e) {
System.out.println("Thread is interrupted, will exit");
Thread.currentThread().interrupt(); // 继续下一次的循环检查
}
}
System.out.println("Lock has been released");
}
});
Thread runningThread = new Thread(() -> {
System.out.println("I'm running");
LockSupport.park(); // 阻塞线程
});
waitingThread.start();
runningThread.start();
Thread.sleep(100);
waitingThread.interrupt(); // 中断等待线程,并释放锁
waitingThread.join();
runningThread.join();
}
}
Running
Running
Running
Running
Thread is interrupted, will exit
Lock has been released
I'm running
Process finished with exit code 0
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java多线程之中断线程(Interrupt)的使用详解 - Python技术站