停止在 Java 中執行更多代碼
1. 概述
我們知道,Java 中可以在一定時間後停止執行。有時,在某些情況下,我們可能希望在某些條件下停止執行進一步的代碼。在本教程中,我們將探索此問題的不同解決方案。
2.問題介紹
當我們想要終止長時間運行的進程、中斷正在運行的Thread,
或處理異常情況時,停止執行更多代碼可能很有用。這增強了我們計劃的控制力和靈活性。
停止執行更多代碼可以實現高效的資源利用,允許正確的錯誤處理,並允許優雅地處理意外情況。這在以下領域可能會有所幫助:
- 高效的CPU利用率
- 內存管理
- 文件和 I/O 資源
- 能源管理
一個例子是在後台運行Thread
。我們知道創建和運行Thread
計算成本很高。當我們不再需要後台Thread,
我們應該中斷並停止它以節省計算資源:
@Override
public void run() {
while (!isInterrupted()) {
if (isInterrupted()) {
break;
}
// complex calculation
}
}
3.使用return
語句
從數學上講,非負整數 n 的階乘(表示為 n!)是從 1 到 n 的所有正整數的乘積。階乘函數可以遞歸地定義:
n! = n * (n - 1)!
0! = 1
下面的calculateFactorial(n)
方法計算所有小於或等於n
的正整數的乘積:
int calculateFactorial(int n) {
if (n <= 1) {
return 1; // base case
}
return n * calculateFactorial(n - 1);
}
在這裡,我們使用return
語句作為該遞歸函數的基本情況。如果n
等於或小於1
,則該函數返回1
。但如果n
大於或等於2
,該函數將計算階乘並返回值。
return
語句的另一個例子是下載文件。如果download()
方法中的fileUrl
和destinationPath
為null
或為空,我們將停止執行進一步的代碼:
void download(String fileUrl, String destinationPath) throws MalformedURLException {
if (fileUrl == null || fileUrl.isEmpty() || destinationPath == null || destinationPath.isEmpty()) {
return;
}
// execute downloading
URL url = new URL(fileUrl);
try (InputStream in = url.openStream(); FileOutputStream out = new FileOutputStream(destinationPath)) {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = in.read(buffer)) != -1) {
out.write(buffer, 0, bytesRead);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
4. 在循環中使用break
語句
要計算數組的總和,我們可以使用一個簡單的 Java for
循環。但是,當數組中存在負值時,該方法停止計算數組的進一步值,並且break
語句終止循環。結果,控制流被重定向到緊跟在for loop
結束之後的語句:
int calculateSum(int[] x) {
int sum = 0;
for (int i = 0; i < 10; i++) {
if (x[i] < 0) {
break;
}
sum += x[i];
}
return sum;
}
要退出循環的特定迭代,我們可以使用break
語句退出循環範圍:
@Test
void givenArrayWithNegative_whenStopExecutionInLoopCalled_thenSumIsCalculatedIgnoringNegatives() {
StopExecutionFurtherCode stopExecutionFurtherCode = new StopExecutionFurtherCode();
int[] nums = { 1, 2, 3, -1, 1, 2, 3 };
int sum = stopExecutionFurtherCode.calculateSum(nums);
assertEquals(6, sum);
}
5. 在標記循環中使用break
語句
帶標籤的break
終止外循環。一旦外循環完成其迭代,程序的執行自然會轉移到後續語句。
這裡, processLines()
方法接受一個String
數組並打印該行。但是,當程序在數組中遇到stop
時,它會停止打印該行並使用break
語句退出標記循環的範圍:
int processLines(String[] lines) {
int statusCode = 0;
parser:
for (String line : lines) {
System.out.println("Processing line: " + line);
if (line.equals("stop")) {
System.out.println("Stopping parsing...");
statusCode = -1;
break parser; // Stop parsing and exit the loop
}
System.out.println("Line processed.");
}
return statusCode;
}
6. 使用boolean
變量
要停止執行更多代碼,我們可以使用標誌變量.
System.exit(0)
通常用於終止當前正在運行的 Java 程序,退出狀態為0
。
在這裡,我們使用條件語句來確定程序是否應該繼續運行或終止:
public class StopExecutionFurtherCode {
boolean shouldContinue = true;
int performTask(int a, int b) {
if (!shouldContinue) {
System.exit(0);
}
return a + b;
}
void stop() {
this.shouldContinue = false;
}
}
如果shouldContinue
為false
,我們會在到達return
語句之前使用System.exit(0)
終止程序。
如果使用參數10
和20
調用performTask()
方法,並且shouldContinue
狀態為false
,則程序將停止執行。此方法不是給出數字的總和,而是終止程序:
StopExecutionFurtherCode stopExecution = new StopExecutionFurtherCode();
stopExecution.stop();
int performedTask = stopExecution.performTask(10, 20);
進行批處理時,有很多長時間運行的任務。我們可以在完成批處理後通知操作系統狀態。當我們使用System.exit(statusCode)
時,操作系統可以判斷關閉是正常還是異常。我們可以使用System.exit(0)
進行正常關閉,使用System.exit(1)
進行異常關閉。
7. 使用Exception
異常是應用程序面臨的意外錯誤或異常情況,需要適當處理。了解錯誤和異常非常重要。在這個例子中,我們需要泛型來檢查參數類型。如果參數類型是Number,
我們使用Exception
來停止方法的執行:
<T> T stopExecutionUsingException(T object) {
if (object instanceof Number) {
throw new IllegalArgumentException("Parameter can not be number.");
}
T upperCase = (T) String.valueOf(object).toUpperCase(Locale.ENGLISH);
return upperCase;
}
在這裡,我們看到每當我們傳遞一個Number
作為參數時,它就會拋出一個Exception
。另一方面,如果我們傳遞String
作為輸入參數,它將返回給定 S tring
的大寫:
@Test
void givenName_whenStopExecutionUsingExceptionCalled_thenNameIsConvertedToUpper() {
StopExecutionFurtherCode stopExecutionFurtherCode = new StopExecutionFurtherCode();
String name = "John";
String result1 = stopExecutionFurtherCode.stopExecutionUsingException(name);
assertEquals("JOHN", result1);
try {
Integer number1 = 10;
assertThrows(IllegalArgumentException.class, () -> {
int result = stopExecutionFurtherCode.stopExecutionUsingException(number1);
});
} catch (Exception e) {
Assert.fail("Unexpected exception thrown: " + e.getMessage());
}
}
在此示例中,我們使用了 Java 泛型的基礎知識。泛型對於類型安全、編譯時類型檢查、集合框架等很有用。
8. 在Thread
中使用interrupt()
方法
讓我們創建一個名為InterruptThread
類,以便在正在運行的線程中使用interrupt()
方法。
當一個線程被中斷時,它會設置該線程的中斷標誌,表明它已被請求停止。如果線程收到中斷信號,它將停止程序中的while loop
範圍:
class InterruptThread extends Thread {
@Override
public void run() {
while (!isInterrupted()) {
if (isInterrupted()) {
break;
}
// business logic
}
}
}
我們需要使用start()
方法啟動一個線程並暫停程序2000ms。然後使用interrupt()
信號停止while loop
中的執行並停止線程:
@Test
void givenThreadRunning_whenInterruptCalled_thenThreadExecutionIsStopped() throws InterruptedException {
InterruptThread stopExecution = new InterruptThread();
stopExecution.start();
Thread.sleep(2000);
stopExecution.interrupt();
stopExecution.join();
assertTrue(!stopExecution.isAlive());
}
9. 結論
在本文中,我們探索了多種編程方法來停止 Java 程序中進一步代碼的執行。要停止程序,我們可以使用System.exit(0)
立即終止。或者, return
和break
語句有助於退出特定方法或循環,而異常則允許中斷代碼執行。
與往常一樣,本文的完整代碼示例可以在 GitHub 上找到。