跳到主要內容

Concurrency - 多執行緒

  好


頻道需要你的支持,謝謝你成為我們的會員(加入會員)

影片1 多執緒程式的基本觀念與建立 Thread 類別



影片2 Thread, Runnable 的使用與 ExecutorService 的基本觀念與建置(上傳錯誤, 己於2025 01 10重新上傳) 



影片3 ExecutorService, Runnable, Callable, Future 的使用



影片4 多執行緒程式的同步, 非同步的基本觀念與建置



影片5 多執行緒程式的同步化方式與 Atomic package 類別的使用



影片6 CyclicBarrier 與 Thread-Safe Collections



範例


一、多執行緒程式

多執行緒程式將程式分成多個獨立的執行單元,稱為「執行緒」。每一個執行緒都可以獨立執行,並與其他執行緒同時運行。作業系統會在這些執行緒之間快速切換,讓它們看起來像是同時執行。

多執行緒程式的好處:

l   提升效能: 特別是在多CPU處理器上,多執行緒可以充分利用每個CPU,加快程式執行速度。

l   增強回應性: 即使程式的一部分被阻塞(例如等待網路回應),其他部分仍然可以繼續執行,保持程式的回應性。

l   提高資源利用率: 多執行緒可以更有效地利用系統資源,例如 CPU 和記憶體。

l   簡化程式設計: 對於某些類型的應用程式,例如圖形用戶界面和網路伺服器,多執行緒可以簡化程式設計。

 

二、Thread / Runnable

在 Java 中,Thread 類別和 Runnable 介面都是用來建立和管理執行緒的工具,但它們有一些關鍵的差異:

1.      定義方式

A.         Thread:是一個類別,你可以透過繼承 Thread 類別來建立執行緒類別。

B.         Runnable:是一個介面,你可以透過實作 Runnable 介面來建立執行緒類別。

2.      繼承限制

A.         Thread:由於 Java 不支援多重繼承,如果你已經繼承了其他類別,就無法再繼承 Thread。

B.         Runnable:可以透過實作 Runnable 介面來建立執行緒,同時還可以繼承其他類別,保有程式設計的彈性。

3.      建立執行緒

A.         Thread:

                            i.                建立一個繼承 Thread 的類別。

                          ii.                覆寫 run() 方法,在其中定義執行緒要執行的程式碼。

                        iii.                建立 Thread 類別的實例。

                        iv.                呼叫 start() 方法啟動執行緒。

B.         Runnable:

                            i.                建立一個實作 Runnable 介面的類別。

                          ii.                實作 run() 方法,在其中定義執行緒要執行的程式碼。

                        iii.                建立 Runnable 類別的實例。

                        iv.                建立 Thread 類別的實例,並將 Runnable 實例作為參數傳遞給 Thread 的建構函式。

                          v.                呼叫 start() 方法啟動執行緒。

 

三、ExecutorService

在 Java 中,ExecutorService 是一個介面,它提供了一種更有效率且更易於管理的方式來處理多執行緒。它可以讓你提交任務並讓執行緒池中的執行緒來執行這些任務,而不用手動建立和管理個別的執行緒。

1.      基本觀念

ExecutorService 的核心概念是執行緒池。執行緒池會預先建立一定數量的執行緒,並將提交的任務分配給這些執行緒執行。這樣可以避免頻繁地建立和銷毀執行緒,提高效率並降低資源消耗。

2.      建立 ExecutorService

在 Java 中,您可以透過 Executors 類別提供的工廠方法來取得 ExecutorService 的實例。這些工廠方法提供不同的執行緒池配置,以滿足不同的需求。以下說明兩種常見的 ExecutorService 取得方式及其差異:

l   Executors.newFixedThreadPool(int count)

l   Executors.newCachedThreadPool()

3.      提交任務

l   使用 execute() 方法將任務提交給 ExecutorService。

l   使用 submit() 方法將任務提交給 ExecutorService。

4.      關閉 ExecutorService

當你不再需要 ExecutorService 時,應該呼叫 shutdown() 方法來關閉它。shutdown() 方法會停止接受新的任務,並等待所有已提交的任務完成後再關閉執行緒池。

 

四、Callable / Future

1.      Callable<T>

l   Callable<T> 是一個介面,它定義了一個 T call() 方法。

l   T call() 方法封裝了您想要非同步執行的任務邏輯,並且它可以返回一個結果。

2.      Future<T>

l   Future<T> 是一個介面,它表示一個計算的結果。

l   它提供了一些方法來檢查計算是否完成、等待計算完成、以及獲取計算的結果。

l   Future<T> 的泛型類型指定了計算返回的結果類型。

 

五、Synchronized / Asynchronized

在程式設計中,Synchronized(同步)和 Asynchronized(非同步)代表了兩種截然不同的執行模型,它們對程式流程、資源管理和用戶體驗都有深遠的影響。

1.      多執行緒程式預設為 Asynchronized 。

2.      設定 Synchronized

l   方法宣告

l   區塊宣告

3.      Static synchronization

l   方法宣告

l   區塊宣告

 

六、atomic package

java.util.concurrent.atomic package提供了強大的工具,用於在 Java 中實現高效率、執行緒安全的程式碼。透過使用 atomic類別,您可以避免傳統鎖定機制帶來的成本,同時確保多執行緒環境下的資料一致性。

 

七、CyclicBarrier

CyclicBarrier 是 Java 中一種強大的同步工具,它能夠有效地協調多個執行緒的執行,確保它們在關鍵時刻同步。透過合理地使用 CyclicBarrier,您可以更好地管理多執行緒程式,提高程式的並行性和效率。

 

八、Thread-Safe Collections

Java 提供了多種執行緒安全的集合,讓您能夠在多執行緒環境中安全地操作集合資料。選擇合適的集合,並遵循正確的使用方式,可以幫助您構建高效能、可靠的多執行緒應用程式。

1.      ConcurrentHashMap

HashMap 的執行緒安全版本。

2.      CopyOnWriteArrayList

ArrayList 的執行緒安全版本。

3.      ConcurrentSkipListMap

TreeMap的執行緒安全版本。

4.      ConcurrentSkipListSet

TreeSet 的執行緒安全版本。

5.      BlockingQueue

常見的實作類別包括ArrayBlockingQueue、LinkedBlockingQueue 和 PriorityBlockingQueue。

n   一種特殊的 Queue,支援阻塞操作。

n   當佇列為空時,從佇列中獲取元素的執行緒將被阻塞,直到有元素可用。

n   當佇列已滿時,向佇列中添加元素的執行緒將被阻塞,直到有空間可用。