
Java 教程
- Java - 首頁
- Java - 概述
- Java - 歷史
- Java - 特性
- Java 與 C++
- JVM - Java 虛擬機器
- Java - JDK 與 JRE 與 JVM
- Java - Hello World 程式
- Java - 環境搭建
- Java - 基本語法
- Java - 變數型別
- Java - 資料型別
- Java - 型別轉換
- Java - Unicode 系統
- Java - 基本運算子
- Java - 註釋
- Java - 使用者輸入
- Java - 日期和時間
Java 控制語句
- Java - 迴圈控制
- Java - 決策制定
- Java - If-else
- Java - Switch
- Java - For 迴圈
- Java - For-Each 迴圈
- Java - While 迴圈
- Java - do-while 迴圈
- Java - Break
- Java - Continue
面向物件程式設計
- Java - OOPs 概念
- Java - 物件和類
- Java - 類屬性
- Java - 類方法
- Java - 方法
- Java - 變數作用域
- Java - 建構函式
- Java - 訪問修飾符
- Java - 繼承
- Java - 聚合
- Java - 多型
- Java - 重寫
- Java - 方法過載
- Java - 動態繫結
- Java - 靜態繫結
- Java - 例項初始化塊
- Java - 抽象
- Java - 封裝
- Java - 介面
- Java - 包
- Java - 內部類
- Java - 靜態類
- Java - 匿名類
- Java - 單例類
- Java - 包裝類
- Java - 列舉
- Java - 列舉建構函式
- Java - 列舉字串
Java 內建類
Java 檔案處理
Java 錯誤和異常
- Java - 異常
- Java - try-catch 塊
- Java - try-with-resources
- Java - 多重 catch 塊
- Java - 巢狀 try 塊
- Java - Finally 塊
- Java - throw 異常
- Java - 異常傳播
- Java - 內建異常
- Java - 自定義異常
Java 多執行緒
- Java - 多執行緒
- Java - 執行緒生命週期
- Java - 建立執行緒
- Java - 啟動執行緒
- Java - 執行緒連線
- Java - 執行緒命名
- Java - 執行緒排程器
- Java - 執行緒池
- Java - 主執行緒
- Java - 執行緒優先順序
- Java - 守護執行緒
- Java - 執行緒組
- Java - 關閉鉤子
Java 同步
Java 網路
- Java - 網路
- Java - 套接字程式設計
- Java - URL 處理
- Java - URL 類
- Java - URLConnection 類
- Java - HttpURLConnection 類
- Java - Socket 類
- Java - 泛型
Java 集合
Java 介面
Java 資料結構
Java 集合演算法
高階 Java
- Java - 命令列引數
- Java - Lambda 表示式
- Java - 傳送郵件
- Java - Applet 基礎
- Java - Javadoc 註釋
- Java - 自動裝箱和拆箱
- Java - 檔案不匹配方法
- Java - REPL (JShell)
- Java - 多版本 Jar 檔案
- Java - 私有介面方法
- Java - 內部類菱形運算子
- Java - 多解析度影像 API
- Java - 集合工廠方法
- Java - 模組系統
- Java - Nashorn JavaScript
- Java - Optional 類
- Java - 方法引用
- Java - 函式式介面
- Java - 預設方法
- Java - Base64 編碼解碼
- Java - Switch 表示式
- Java - Teeing 收集器
- Java - 微基準測試
- Java - 文字塊
- Java - 動態 CDS 歸檔
- Java - Z 垃圾收集器 (ZGC)
- Java - 空指標異常
- Java - 打包工具
- Java - 密封類
- Java - 記錄類
- Java - 隱藏類
- Java - 模式匹配
- Java - 緊湊數字格式化
- Java - 垃圾回收
- Java - JIT 編譯器
Java 雜項
- Java - 遞迴
- Java - 正則表示式
- Java - 序列化
- Java - 字串
- Java - Process API 改進
- Java - Stream API 改進
- Java - 增強的 @Deprecated 註釋
- Java - CompletableFuture API 改進
- Java - 流
- Java - 日期時間 API
- Java 8 - 新特性
- Java 9 - 新特性
- Java 10 - 新特性
- Java 11 - 新特性
- Java 12 - 新特性
- Java 13 - 新特性
- Java 14 - 新特性
- Java 15 - 新特性
- Java 16 - 新特性
Java API 和框架
Java 類引用
- Java - Scanner
- Java - 陣列
- Java - 字串
- Java - Date
- Java - ArrayList
- Java - Vector
- Java - Stack
- Java - PriorityQueue
- Java - LinkedList
- Java - ArrayDeque
- Java - HashMap
- Java - LinkedHashMap
- Java - WeakHashMap
- Java - EnumMap
- Java - TreeMap
- Java - IdentityHashMap
- Java - HashSet
- Java - EnumSet
- Java - LinkedHashSet
- Java - TreeSet
- Java - BitSet
- Java - Dictionary
- Java - Hashtable
- Java - Properties
- Java - Collection
- Java - Array
Java 有用資源
Java - 可重入監視器
Java 中的可重入監視器
ReetrantLock 是一個實現 Lock 介面的類。它提供了 同步 功能,具有很強的靈活性,因此它是 Java 中使用最多的鎖類。它對於執行緒的可靠和 公平工作 是必要的。這裡,執行緒是大操作的小子程序。在本文中,我們將學習 ReetrantLock 以及它們如何管理執行緒以使其能夠高效地工作。
ReetrantLock 的工作原理
當 多個執行緒 嘗試訪問共享資源時,ReetrantLock 透過 lock() 和 unlock() 方法一次限制一個執行緒訪問。假設有三人試圖預訂火車票。同時,這三個人都會嘗試訪問預訂系統,可能會發生兩個人最終預訂了同一個座位的情況。Reetrant Lock 可以處理這種情況。
首先,這三個人都會透過 tryLock() 方法請求獲取預訂系統。當一個人獲取預訂系統後,它會透過 lock() 方法限制特定的座位預訂。預訂後,該人將呼叫 unlock() 方法釋放獲取的鎖。在資源繁忙期間,其他人將排隊等待輪到他們,並在鎖釋放後進入可執行狀態。
ReetrantLock 試圖以公平的方式提供鎖。我們可以設定執行緒可以獲取鎖的時間長度,並且它還可以確保等待時間最長的執行緒可能首先獲取鎖。預設情況下,鎖是不公平的,要使其公平,我們需要在其建構函式中傳遞布林值 true。
語法
ReentrantLock nameOflock = new ReentrantLock(); // by default false Or, ReentrantLock nameOflock = new ReentrantLock(true); // we can make it true
鎖是顯式的,可以按任何順序鎖定或解鎖。單個執行緒可以多次請求鎖,這就是鎖名稱為可重入的原因。我們可以使用 getHoldCount() 方法計算鎖被獲取的次數。
沒有可重入鎖的多執行緒
以下示例說明了在上述程式碼中未使用可重入鎖的多執行緒。我們建立了一個名為 Thrd 的類,其中包含一個名為 operation() 的方法來執行給定的任務。現在,我們建立了三個執行緒類並呼叫 operation() 方法。在 main() 方法中,定義了執行緒類的三個物件,並使用它們的 start() 方法 來啟動執行緒的執行。
沒有可重入鎖的多執行緒示例
package com.tutorialspoint; class Thrd { static void operation(int data) { for(int i = 1; i <= 4; i++) { System.out.println(data++); } } } class Thrd1 extends Thread { // thread number 1 public void run() { Thrd.operation(1); // method calling } } class Thrd2 extends Thread { // thread number 2 public void run() { Thrd.operation(5); // method calling } } class Thrd3 extends Thread { // thread number 3 public void run() { Thrd.operation(10); // method calling } } public class TestThread { public static void main(String args[]) { // creating object for thread class Thrd1 oprt1 = new Thrd1(); Thrd2 oprt2 = new Thrd2(); Thrd3 oprt3 = new Thrd3(); // Starting the thread operation oprt1.start(); oprt2.start(); oprt3.start(); } }
每次執行此程式時,這都會產生不同的結果 -
輸出
1 2 3 4 10 11 12 13 5 6 7 8
使用可重入鎖的多執行緒
以下示例說明了在上述程式碼中使用可重入鎖。我們建立了一個名為 Thrd 的類,並在該執行緒內部,我們定義了一個 ReentrantLock 的物件。一個名為 operation() 的方法將 tryLock() 方法的布林值儲存到名為 lockAcquired 的變數中,該變數將檢查鎖是否被任何執行緒獲取。如果獲取了鎖,則使用 lock() 方法將鎖授予該執行緒,然後執行緒開始執行給定的任務。該任務將在 try 塊中執行,並且鎖將在 finally 塊中使用 unlock() 方法釋放。現在,我們建立了三個執行緒類並呼叫 operation() 方法。在 main() 方法中,定義了執行緒類的三個物件,並使用它們的 start() 方法來啟動執行緒的執行。
使用可重入鎖的多執行緒示例
package com.tutorialspoint; import java.util.concurrent.locks.ReentrantLock; class Thrd { // creating object of ReentrantLock class private static ReentrantLock lockr = new ReentrantLock(); static void operation(int data) { // give access to lock boolean lockAcquired = lockr.tryLock(); if (lockAcquired) { try { lockr.lock(); // giving lock to thread for(int i = 1; i <= 4; i++) { System.out.println(data++); } // checking lock count System.out.println("Count of Lock: " + lockr.getHoldCount()); } finally { lockr.unlock(); // unlocking the lock } } else { System.out.println("I am in else block"); } } } class Thrd1 extends Thread { // thread number 1 public void run() { Thrd.operation(1); // method calling } } class Thrd2 extends Thread { // thread number 2 public void run() { Thrd.operation(5); // method calling } } class Thrd3 extends Thread { // thread number 3 public void run() { Thrd.operation(10); // method calling } } public class TestThread { public static void main(String args[]) { // creating object for thread class Thrd1 oprt1 = new Thrd1(); Thrd2 oprt2 = new Thrd2(); Thrd3 oprt3 = new Thrd3(); // Starting the thread operation oprt1.start(); oprt2.start(); oprt3.start(); } }
每次執行此程式時,這都會產生不同的結果 -
輸出
I am in else block 5 6 7 8 Count of Lock: 2 I am in else block
將可重入鎖設定為 True 的多執行緒
以下示例說明了在上述程式碼中使用 Reentrant Lock 的方法。我們建立了一個類Thrd,並在該執行緒內部,我們定義了一個 ReentrantLock 物件,其公平值為 true。方法 operation() 將tryLock()方法的布林值儲存到名為lockAcquired的變數中,該變數將檢查鎖是否被任何執行緒獲取。如果獲取了鎖,則使用lock()方法將鎖授予該執行緒,然後執行緒開始執行給定的任務。該任務將在 try 塊中執行,並在 finally 塊中使用unlock()方法釋放鎖。現在我們建立了三個執行緒類並呼叫了operation()方法。在 main() 方法中,定義了三個執行緒類的物件,並呼叫它們的start()方法以啟動執行緒的執行。
Reentrant Lock 為 True 的多執行緒示例
package com.tutorialspoint; import java.util.concurrent.locks.ReentrantLock; class Thrd { // creating object of ReentrantLock class private static ReentrantLock lockr = new ReentrantLock(true); static void operation(int data) { // give access to lock boolean lockAcquired = lockr.tryLock(); if (lockAcquired) { try { lockr.lock(); // giving lock to thread for(int i = 1; i <= 4; i++) { System.out.println(data++); } // checking lock count System.out.println("Count of Lock: " + lockr.getHoldCount()); } finally { lockr.unlock(); // unlocking the lock } } else { System.out.println("I am in else block"); } } } class Thrd1 extends Thread { // thread number 1 public void run() { Thrd.operation(1); // method calling } } class Thrd2 extends Thread { // thread number 2 public void run() { Thrd.operation(5); // method calling } } class Thrd3 extends Thread { // thread number 3 public void run() { Thrd.operation(10); // method calling } } public class TestThread { public static void main(String args[]) { // creating object for thread class Thrd1 oprt1 = new Thrd1(); Thrd2 oprt2 = new Thrd2(); Thrd3 oprt3 = new Thrd3(); // Starting the thread operation oprt1.start(); oprt2.start(); oprt3.start(); } }
每次執行此程式時,這都會產生不同的結果 -
輸出
I am in else block I am in else block 5 6 7 8 Count of Lock: 2