文章目錄
- 一、完整代碼
- 二、代碼解釋
- 1、方法簽名
- 2、初始化CountDownLatch
- 3、提交任務到執行器
- 4、任務線程的邏輯
- 5、主線程的邏輯
- 詳細解釋
- 總結
以下代碼實現了一個簡單的框架,用于測量并發執行任務的時間。它使用了Executor來執行任務,并通過CountDownLatch來協調多個線程的執行。
假設我們使用一個簡單的任務(如打印線程名稱和任務編號),并運行這個方法。
一、完整代碼
import java.util.concurrent.*;// Simple framework for timing concurrent execution
public static long time(Executor executor, int concurrency, Runnable action) throws InterruptedException {// 創建一個計數器,用于確保所有任務線程都已準備好CountDownLatch ready = new CountDownLatch(concurrency);// 創建一個計數器,用于通知所有任務線程開始執行CountDownLatch start = new CountDownLatch(1);// 創建一個計數器,用于確保所有任務線程都已完成CountDownLatch done = new CountDownLatch(concurrency);// 提交 concurrency 個任務到執行器for (int i = 0; i < concurrency; i++) {executor.execute(() -> {// 每個任務線程在開始執行前調用 countDown,表示已準備好ready.countDown(); // Tell timer we're readytry {// 每個任務線程等待 start 的計數器變為 0,即等待主線程通知開始執行start.await(); // Wait till peers are ready// 執行傳入的 Runnable 任務action.run();} catch (InterruptedException e) {// 如果捕獲到 InterruptedException,重新設置當前線程的中斷狀態Thread.currentThread().interrupt();} finally {// 每個任務線程執行完畢后,調用 countDown,表示已完成done.countDown(); // Tell timer we're done}});}// 主線程等待所有任務線程都準備好ready.await(); // Wait for all workers to be ready// 記錄開始時間long startNanos = System.nanoTime();// 主線程通知所有任務線程開始執行start.countDown(); // And they're off!// 主線程等待所有任務線程都完成done.await(); // Wait for all workers to finish// 計算并返回任務執行的總時間(納秒)return System.nanoTime() - startNanos;
}
為了更直觀地理解這段代碼的運行邏輯和輸出效果,我們可以補充具體的輸入參數,并展示完整的運行過程和最終輸出。假設我們使用一個簡單的任務(如打印線程名稱和任務編號),并運行這個方法。
import java.util.concurrent.*;public class ConcurrentTimingFramework {// Simple framework for timing concurrent executionpublic static long time(Executor executor, int concurrency, Runnable action) throws InterruptedException {// 創建一個計數器,用于確保所有任務線程都已準備好CountDownLatch ready = new CountDownLatch(concurrency);// 創建一個計數器,用于通知所有任務線程開始執行CountDownLatch start = new CountDownLatch(1);// 創建一個計數器,用于確保所有任務線程都已完成CountDownLatch done = new CountDownLatch(concurrency);// 提交 concurrency 個任務到執行器for (int i = 0; i < concurrency; i++) {executor.execute(() -> {// 每個任務線程在開始執行前調用 countDown,表示已準備好ready.countDown(); // Tell timer we're readytry {// 每個任務線程等待 start 的計數器變為 0,即等待主線程通知開始執行start.await(); // Wait till peers are ready// 執行傳入的 Runnable 任務action.run();} catch (InterruptedException e) {// 如果捕獲到 InterruptedException,重新設置當前線程的中斷狀態Thread.currentThread().interrupt();} finally {// 每個任務線程執行完畢后,調用 countDown,表示已完成done.countDown(); // Tell timer we're done}});}// 主線程等待所有任務線程都準備好ready.await(); // Wait for all workers to be ready// 記錄開始時間long startNanos = System.nanoTime();// 主線程通知所有任務線程開始執行start.countDown(); // And they're off!// 主線程等待所有任務線程都完成done.await(); // Wait for all workers to finish// 計算并返回任務執行的總時間(納秒)return System.nanoTime() - startNanos;}public static void main(String[] args) throws InterruptedException {// 創建一個線程池,線程池大小為 4ExecutorService executor = Executors.newFixedThreadPool(4);// 定義并發級別int concurrency = 4;// 定義要執行的任務Runnable action = () -> {System.out.println("Task executed by " + Thread.currentThread().getName());};// 調用 time 方法,測量并發執行的時間long duration = time(executor, concurrency, action);// 打印執行時間System.out.println("Total execution time: " + duration + " nanoseconds");// 關閉線程池executor.shutdown();}
}
假設運行環境中有足夠的線程資源,輸出可能如下:
Task executed by pool-1-thread-1
Task executed by pool-1-thread-2
Task executed by pool-1-thread-3
Task executed by pool-1-thread-4
Total execution time: 1234567 nanoseconds
二、代碼解釋
1、方法簽名
public static long time(Executor executor, int concurrency, Runnable action) throws InterruptedException {
參數:
- Executor executor:一個執行器,用于執行任務。
- int concurrency:并發級別,即同時運行的任務數量。
- Runnable action:要執行的任務。
- 返回值:long,表示任務執行的總時間(納秒)。
- 異常:throws InterruptedException,表示方法可能會拋出InterruptedException。
2、初始化CountDownLatch
CountDownLatch ready = new CountDownLatch(concurrency);
CountDownLatch start = new CountDownLatch(1);
CountDownLatch done = new CountDownLatch(concurrency);
- ready:用于確保所有任務線程都已準備好。
- start:用于通知所有任務線程開始執行。
- done:用于確保所有任務線程都已完成。
3、提交任務到執行器
for (int i = 0; i < concurrency; i++) {executor.execute(() -> {
- 提交concurrency個任務到executor。
- 每個任務是一個Runnable,使用Lambda表達式實現。
4、任務線程的邏輯
ready.countDown(); // Tell timer we're ready
try {start.await(); // Wait till peers are readyaction.run();
} catch (InterruptedException e) {Thread.currentThread().interrupt();
} finally {done.countDown(); // Tell timer we're done
}
- ready.countDown():每個任務線程在開始執行前調用countDown,表示已準備好。
- start.await():任務線程等待start的計數器變為0,即等待主線程通知開始執行。
- action.run():執行傳入的Runnable任務。
- catch (InterruptedException e):捕獲InterruptedException,并重新設置當前線程的中斷狀態。
- done.countDown():任務線程執行完畢后,調用countDown,表示已完成。
5、主線程的邏輯
ready.await(); // Wait for all workers to be ready
long startNanos = System.nanoTime();
start.countDown(); // And they're off!
done.await(); // Wait for all workers to finish
return System.nanoTime() - startNanos;
- ready.await():主線程等待所有任務線程都準備好。
- startNanos = System.nanoTime():記錄開始時間。
- start.countDown():主線程通知所有任務線程開始執行。
- done.await():主線程等待所有任務線程都完成。
- return System.nanoTime() - startNanos:計算并返回任務執行的總時間(納秒)。
詳細解釋
- 任務線程的準備階段:
每個任務線程調用ready.countDown(),表示已準備好。
主線程調用ready.await(),等待所有任務線程準備好。 - 任務線程的執行階段:
主線程調用start.countDown(),通知所有任務線程開始執行。
每個任務線程調用start.await(),等待主線程的通知。
任務線程執行action.run(),打印當前線程的名稱。 - 任務線程的完成階段:
每個任務線程調用done.countDown(),表示已完成。
主線程調用done.await(),等待所有任務線程完成。 - 計算執行時間:
主線程記錄任務開始時間和結束時間,計算總時間并返回。
總結
通過這個示例,我們可以看到time方法如何使用CountDownLatch來協調多個任務線程的執行,并測量任務的總執行時間。希望這個詳細的解釋和示例能幫助你更好地理解代碼的運行邏輯和輸出效果!