Java線程中斷及線程中斷的幾種使用場景小結(jié)
引言
在多線程編程中,線程中斷技術(shù)是確保程序健壯性和可靠性的不可或缺的一部分。本文將深入探討Java中的線程中斷技術(shù),以通俗易懂的方式介紹其概念、機(jī)制以及在實(shí)際項(xiàng)目中的應(yīng)用。
1. 線程中斷概述
在多線程編程中,線程是程序中的執(zhí)行單元,而線程中斷是一種機(jī)制,允許一個線程打斷另一個線程的正常執(zhí)行流程。這種機(jī)制為多線程環(huán)境下的協(xié)同工作提供了一種靈活而有效的方式。
線程中斷并不是強(qiáng)制性的,而是一種協(xié)作機(jī)制。通過線程中斷,我們可以向目標(biāo)線程發(fā)出信號,通知它發(fā)生了一些特定的事件,而目標(biāo)線程可以選擇如何應(yīng)對這個事件。這種靈活性使得線程中斷成為并發(fā)編程中的一個重要工具。
以下是與線程中斷相關(guān)的幾個核心方法:
interrupt()方法:
作用: 用于中斷目標(biāo)線程,將目標(biāo)線程的中斷標(biāo)志位置為true。調(diào)用方式: Thread.currentThread().interrupt() 或 myThread.interrupt()。
isInterrupted()方法:
作用: 返回調(diào)用線程的中斷狀態(tài),不會清除中斷標(biāo)志。調(diào)用方式: Thread.currentThread().isInterrupted() 或 myThread.isInterrupted()。
interrupted()方法:
作用: 返回調(diào)用線程的中斷狀態(tài),并清除中斷標(biāo)志(靜態(tài)方法)。調(diào)用方式: Thread.interrupted()。
**注意:**這里的myThread代表的是你創(chuàng)建的線程實(shí)例的名字
2. Java中的線程中斷機(jī)制
在Java中,線程中斷是通過Thread類提供的interrupt()方法來實(shí)現(xiàn)的。調(diào)用interrupt()方法并不會直接中斷線程,而是將線程的中斷標(biāo)志位置為true,表示線程已經(jīng)被中斷。目標(biāo)線程可以通過檢查自身的中斷狀態(tài)來確定是否被中斷,從而采取相應(yīng)的行動。
這種設(shè)計(jì)使得線程中斷變得相對安全,因?yàn)榫€程仍然有機(jī)會在合適的時(shí)候完成它的工作,而不是被強(qiáng)制中止。同時(shí),它也為程序員提供了更細(xì)粒度的控制,可以在適當(dāng)?shù)臅r(shí)候中斷線程,從而提高程序的魯棒性。
例子:
public class InterruptExample {
public static void main(String[] args) {
Thread myThread = new Thread(() -> {
while (!Thread.interrupted()) {
// 線程執(zhí)行的操作
System.out.println("Working...");
}
System.out.println("Thread is interrupted!");
});
myThread.start();
// 在適當(dāng)?shù)臅r(shí)機(jī)調(diào)用 myThread.interrupt() 來中斷線程
try {
Thread.sleep(2000);
myThread.interrupt();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
3. 捕獲中斷信號
在實(shí)際應(yīng)用中,我們需要了解目標(biāo)線程是否被中斷。為此,Java提供了兩種方法:isInterrupted()和Thread.interrupted()。這兩者的區(qū)別在于前者不會改變中斷狀態(tài),而后者會清除中斷狀態(tài)。


Thread.interrupted()示例:
// 示例代碼
public class InterruptCaptureExample {
public static void main(String[] args) {
Thread myThread = new Thread(() -> {
while (!Thread.interrupted()) {
// 線程執(zhí)行的操作
System.out.println("Working...");
}
// 線程中斷狀態(tài)被Thread.interrupted()清除了
System.out.println("Thread is interrupted: " + Thread.interrupted());
});
myThread.start();
// 在適當(dāng)?shù)臅r(shí)機(jī)調(diào)用 myThread.interrupt() 來中斷線程
try {
Thread.sleep(2000);
myThread.interrupt();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
isInterrupted方法示例:
public class InterruptCaptureExample {
public static void main(String[] args) {
Thread myThread = new Thread(() -> {
try {
while (!Thread.interrupted()) {
// 模擬線程執(zhí)行的操作
System.out.println("Working...");
Thread.sleep(500); // 模擬耗時(shí)操作
}
} catch (InterruptedException e) {
System.out.println("Thread is interrupted during work!");
// 重新設(shè)置中斷狀態(tài),因?yàn)門hread.interrupted清除了線程中斷狀態(tài)
// 否則myThread.isInterrupted()為false
Thread.currentThread().interrupt();
} finally {
// 清理工作,確保資源釋放
System.out.println("Cleaning up resources...");
}
});
myThread.start();
// 在適當(dāng)?shù)臅r(shí)機(jī)調(diào)用 myThread.interrupt() 來中斷線程
try {
Thread.sleep(2000);
myThread.interrupt();
} catch (InterruptedException e) {
e.printStackTrace();
}
// 判斷線程是否被中斷
boolean isInterrupted = myThread.isInterrupted();
System.out.println("Thread is interrupted: " + isInterrupted);
}
}
4. 處理中斷
線程被中斷時(shí),應(yīng)該采取哪些操作?本節(jié)提供一些建議,涉及到線程在中斷時(shí)的清理工作和資源釋放,確保線程的優(yōu)雅退出。
例子:
public class CleanupOnInterrupt {
public static void main(String[] args) {
Thread myThread = new Thread(() -> {
try {
while (!Thread.interrupted()) {
// 線程執(zhí)行的操作
System.out.println("Thread is working...");
Thread.sleep(1000); // 模擬線程執(zhí)行任務(wù)
}
} catch (InterruptedException e) {
System.out.println("Thread is interrupted during work!");
} finally {
// 清理工作,確保資源釋放
System.out.println("Cleaning up resources...");
}
});
myThread.start();
try {
// 在適當(dāng)?shù)臅r(shí)機(jī)調(diào)用 myThread.interrupt() 來中斷線程
Thread.sleep(5000); // 模擬主線程等待一段時(shí)間后中斷子線程
myThread.interrupt();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
5. 等待中的線程中斷
本章探討處在等待狀態(tài)中的線程如何響應(yīng)中斷。通過實(shí)例演示wait()和sleep()方法,以及如何使用InterruptedException來處理中斷,使讀者朋友能夠理解這一關(guān)鍵概念。
例子:
public class ThreadWaitInterrupt {
public static void main(String[] args) {
Object lock = new Object();
Thread myThread = new Thread(() -> {
synchronized (lock) {
try {
lock.wait();
} catch (InterruptedException e) {
System.out.println("Thread is interrupted!");
}
}
});
myThread.start();
try {
// 在適當(dāng)?shù)臅r(shí)機(jī)調(diào)用 myThread.interrupt() 來中斷線程
Thread.sleep(3000); // 模擬主線程等待一段時(shí)間后中斷子線程
myThread.interrupt();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
6. 優(yōu)雅的線程中斷
通過一個生動的實(shí)例,演示如何在實(shí)際應(yīng)用中使用線程中斷。以文件下載為例,展示如何通過中斷機(jī)制提高程序的響應(yīng)性和用戶體驗(yàn)。
例子:
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
class FileDownloadThread extends Thread {
private final String fileUrl;
private final String destinationFile;
public FileDownloadThread(String fileUrl, String destinationFile) {
this.fileUrl = fileUrl;
this.destinationFile = destinationFile;
}
@Override
public void run() {
try (InputStream in = new URL(fileUrl).openStream();
FileOutputStream fileOutputStream = new FileOutputStream(destinationFile)) {
byte[] buffer = new byte[1024];
int bytesRead;
while ( (bytesRead = in.read(buffer)) != -1) {
if (isInterrupted()){
System.out.println("File download cancel!");
break;
}else{
fileOutputStream.write(buffer, 0, bytesRead);
}
System.out.println("File download completed!");
}
} catch (IOException e) {
System.out.println("File download failed: " + e.getMessage());
}
}
}
public class DownLoad {
public static void main(String[] args) {
String fileUrl = "https://download.oracle.com/java/21/latest/jdk-21_linux-aarch64_bin.tar.gz";
String destinationFile = "downloadedFile.zip";
FileDownloadThread downloadThread = new FileDownloadThread(fileUrl, destinationFile);
downloadThread.start();
// 模擬用戶點(diǎn)擊取消下載操作
try {
Thread.sleep(1000); // 用戶等待了1秒后取消下載
downloadThread.interrupt();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
在這個例子中,F(xiàn)ileDownloadThread負(fù)責(zé)下載文件,通過檢查線程的中斷狀態(tài)來判斷是否繼續(xù)下載。主線程模擬用戶點(diǎn)擊取消下載操作,調(diào)用downloadThread.interrupt()來中斷文件下載線程。線程在被中斷后,會立即停止下載并輸出相應(yīng)的信息,使用戶體驗(yàn)更加友好。這展示了線程中斷在提高程序響應(yīng)性方面的實(shí)際應(yīng)用。
7. 避免死鎖
死鎖是多線程編程中常見的問題,而線程中斷可以用來避免死鎖。通過在獲取資源時(shí)檢查線程中斷狀態(tài),可以及時(shí)中止可能導(dǎo)致死鎖的線程。
技術(shù)點(diǎn):
- 使用線程中斷來打破死鎖。
- 如何檢查線程中斷狀態(tài)以避免死鎖。
實(shí)現(xiàn):
- 在多線程應(yīng)用中,當(dāng)一個線程等待獲取多個鎖時(shí),可能發(fā)生死鎖。通過在獲取每個鎖的過程中檢查線程中斷狀態(tài),可以避免死鎖的發(fā)生。當(dāng)線程被中斷時(shí),它可以選擇立即釋放已經(jīng)獲取的鎖,防止死鎖的發(fā)生。
public class DeadlockAvoidanceExample {
private final Object lock1 = new Object();
private final Object lock2 = new Object();
public void executeThread1() {
synchronized (lock1) {
System.out.println("Thread 1: Holding lock 1");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
System.out.println("Thread 1: interrupt");
return;
}
System.out.println("Thread 1: Waiting for lock 2");
synchronized (lock2) {
System.out.println("Thread 1: Holding lock 1 and lock 2");
}
}
}
public void executeThread2() {
synchronized (lock2) {
System.out.println("Thread 2: Holding lock 2");
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
System.out.println("Thread 2: interrupt");
//Thread.currentThread().interrupt();
return;
}
System.out.println("Thread 2: Waiting for lock 1");
synchronized (lock1) {
System.out.println("Thread 2: Holding lock 1 and lock 2");
}
}
}
public static void main(String[] args) throws InterruptedException {
DeadlockAvoidanceExample deadlockAvoidanceExample =new DeadlockAvoidanceExample();
Thread t1 = new Thread(){
public void run(){
deadlockAvoidanceExample.executeThread1();
//deadlockAvoidanceExample.executeThread2();
}
};
Thread t2 = new Thread(){
public void run(){
// deadlockAvoidanceExample.executeThread1();
deadlockAvoidanceExample.executeThread2();
}
};
t1.start();
t2.start();
// 主線程sleep 2秒
Thread.sleep(2000);
// 中斷t2線程,釋放鎖,t1線程可以獲得鎖繼續(xù)執(zhí)行
t2.interrupt();
}
執(zhí)行效果如下:

在這個例子中,DeadlockAvoidanceExample類展示了一個可能導(dǎo)致死鎖的情況。通過在獲取鎖的過程中檢查線程中斷狀態(tài),可以在發(fā)生死鎖時(shí)及時(shí)中止線程,從而避免死鎖的發(fā)生。
8. 最佳實(shí)踐和注意事項(xiàng)
總結(jié)線程中斷的最佳實(shí)踐,提醒讀者朋友注意可能的陷阱和常見誤區(qū)。包括如何避免濫用線程中斷,以及在不同場景下的最佳應(yīng)用方式。
技術(shù)點(diǎn):
- 不同場景下的線程中斷最佳實(shí)踐。
- 避免濫用線程中斷的策略。
實(shí)現(xiàn):
- 在使用線程中斷時(shí),確保目標(biāo)線程能夠正確響應(yīng)中斷信號,避免出現(xiàn)死循環(huán)或不響應(yīng)中斷的情況。
- 謹(jǐn)慎處理捕獲的InterruptedException,避免忽略異?;騼H僅輸出日志而不采取實(shí)際行動的情況。
例子:
public class InterruptBestPracticesExample {
public static void main(String[] args) {
Thread myThread = new Thread(() -> {
try {
while (!Thread.interrupted()) {
// 線程執(zhí)行的操作
System.out.println("Thread is working...");
Thread.sleep(1000); // 模擬線程執(zhí)行任務(wù)
}
} catch (InterruptedException e) {
System.out.println("Thread is interrupted during work!");
Thread.currentThread().interrupt(); // 重新設(shè)置中斷狀態(tài)
} finally {
// 清理工作,確保資源釋放
System.out.println("Cleaning up resources...");
}
});
myThread.start();
try {
// 在適當(dāng)?shù)臅r(shí)機(jī)調(diào)用 myThread.interrupt() 來中斷線程
Thread.sleep(5000); // 模擬主線程等待一段時(shí)間后中斷子線程
myThread.interrupt();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
9. 結(jié)論
通過本文的學(xué)習(xí),我們深入剖析了Java線程中斷技術(shù),理解了其核心概念和實(shí)際應(yīng)用。在并發(fā)編程中,合理使用線程中斷機(jī)制可以提高程序的魯棒性和可維護(hù)性。
概括:
- 線程中斷是一種協(xié)作機(jī)制,通過它可以向目標(biāo)線程發(fā)出信號,通知它發(fā)生了一些特定的事件。
- 在Java中,線程中斷是通過Thread類提供的interrupt()方法來實(shí)現(xiàn)的,通過檢查自身的中斷狀態(tài)來確定是否被中斷。
- 我們通過實(shí)例演示了線程中斷的各種應(yīng)用,包括優(yōu)雅的線程中斷、避免死鎖等場景。
- 在實(shí)際應(yīng)用中,合理使用線程中斷可以提高程序的響應(yīng)性和用戶體驗(yàn),但也需要注意避免濫用和正確處理中斷異常。
到此這篇關(guān)于Java線程中斷及線程中斷的幾種使用場景小結(jié)的文章就介紹到這了,更多相關(guān)Java線程中斷內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java:com.netflix.client.ClientException錯誤解決
本文主要介紹了Java:com.netflix.client.ClientException錯誤解決,主要是指出客戶端?module-sso?試圖通過負(fù)載均衡器訪問服務(wù)時(shí),負(fù)載均衡器沒有找到可用的服務(wù)器來處理請求,下面就來介紹一下解決方法2024-08-08
IntelliJ IDEA cmd和idea Terminal查看java版本不一致的解決
原來win10電腦上安裝的是jdk8的版本,因某些原因,現(xiàn)在想換成jdk7的版本,修改環(huán)境變量后,在cmd中執(zhí)行 [java -version]命令,顯示的是7的版本,遇到這樣的問題如何解決呢?下面小編給大家分享IntelliJ IDEA cmd和idea Terminal查看java版本不一致的解決方案,一起看看吧2023-09-09
Spring Boot命令行啟動添加參數(shù)的三種方式
在命令行中,常見的參數(shù)可以分為三類:選項(xiàng)參數(shù)、非選項(xiàng)參數(shù)和系統(tǒng)參數(shù),本文就來介紹一下Spring Boot命令行三種參數(shù)形式,感興趣的可以了解一下2023-09-09
詳解如何在Spring Boot中實(shí)現(xiàn)容錯機(jī)制
容錯機(jī)制是構(gòu)建健壯和可靠的應(yīng)用程序的重要組成部分,它可以幫助應(yīng)用程序在面對異常或故障時(shí)保持穩(wěn)定運(yùn)行,Spring Boot提供了多種機(jī)制來實(shí)現(xiàn)容錯,包括異常處理、斷路器、重試和降級等,本文將介紹如何在Spring Boot中實(shí)現(xiàn)這些容錯機(jī)制,需要的朋友可以參考下2023-10-10
Spring Cloud Alibaba配置多環(huán)境管理詳解與實(shí)戰(zhàn)代碼
本文通過實(shí)際案例詳細(xì)介紹了springboot配置多環(huán)境管理的使用,以及基于nacos的配置多環(huán)境管理的實(shí)踐,在實(shí)際開發(fā)中,配置多環(huán)境管理是一個很難避開的問題,同時(shí)也是微服務(wù)治理中一個很重要的內(nèi)容,感興趣的朋友跟隨小編一起看看吧2024-06-06
SpringCloud+Redis實(shí)現(xiàn)Api接口限流防止惡意刷接口
接口限流是為了保護(hù)系統(tǒng)和服務(wù),防止因?yàn)檫^多的請求而崩潰,本文主要介紹了SpringCloud+Redis實(shí)現(xiàn)Api接口限流防止惡意刷接口,具有一定的參考價(jià)值,感興趣的可以了解一下2024-03-03
java中常用的阻塞隊(duì)列與非阻塞隊(duì)列詳解
這篇文章主要介紹了java中常用的阻塞隊(duì)列與非阻塞隊(duì)列用法,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2025-04-04
聊一聊SpringBoot服務(wù)監(jiān)控機(jī)制
這篇文章主要介紹了聊一聊SpringBoot服務(wù)監(jiān)控機(jī)制,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04

