Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
搞科技教程】LockHTML3是一款鎖屏美化插件,可以更換鎖屏主題,也可以隱藏原生鎖屏的各個項目,例如隱藏控制中心橫桿,通知中心橫桿,解鎖文字等等。而它最重要的功能是可用WinterBoard鎖屏主題,這個就需要我們動動手指下載鎖屏主題。
我們可以在網上搜索下載相關主題素材包,經過解壓后,使用PP助手(電腦端)將主題包導入到“文件-文件系統(tǒng)(越獄)-Library-Theme”下。而LockHTML3是會自動讀取WinterBoard主題文件夾內的鎖屏主題的,因此我們只需直接在LockHTML3中選取即可使用,無需注銷或重啟。
選擇好主題后,你可以對原生鎖屏項目進行適當調整,在LockHTML3中選擇隱藏部分鎖屏顯示項目,例如(上下小橫杠、相機、時鐘、日期、解鎖文字、滑塊、鎖屏狀態(tài)欄、定義全屏通知、鎖屏延時、設置解鎖文字等,使得更換主題后的鎖屏更美觀。
*詳細操作演示及效果展示視頻:
LockHTML3在美化方面功能十分強大,擁有它其它鎖屏插件基本上可以不用了,完全可以滿足你的DIY欲望。
ava內置鎖:深度解析lock和trylock - 程序員古德
“
lock和tryLock是兩種獲取鎖的方式,它們在處理并發(fā)問題時有所不同,lock是阻塞性的,確保只有一個線程能訪問被鎖資源,但可能導致線程長時間等待;而tryLock非阻塞性,若鎖被占用則立即返回失敗,避免了長時間等待,但需要更復雜的邏輯處理未能獲鎖的情況。
Java內置鎖:深度解析lock和trylock - 程序員古德
在Java 11中,Lock接口是Java并發(fā)編程中一個重要的接口,它提供了更靈活的線程同步機制,相比于內置的synchronized關鍵字,Lock接口中主要有兩個方法用于獲取鎖:lock()和tryLock()。
參考文檔:https://docx.iamqiang.com/jdk11/api/java.base/java/util/concurrent/locks/Lock.html
lock()方法是一個阻塞式的方法,當線程調用這個方法時,如果鎖已經被其他線程持有,那么當前線程就會進入等待狀態(tài),直到獲得鎖為止,在這個過程中,線程會一直等待,不會做其他的事情,這就好比在一個繁忙的餐廳外等待空位,如果沒有空位,就只能站著等,不能做其他事情,直到有空位為止。
tryLock()方法則是一個非阻塞式的方法,當線程調用這個方法時,如果鎖已經被其他線程持有,那么這個方法會立即返回,不會讓線程進入等待狀態(tài),如果鎖沒有被其他線程持有,那么當前線程就會立即獲得鎖,這就像在餐廳外等待空位,但是不確定是否有空位,所以先問一下服務員,如果有空位就坐下,如果沒有就去其他地方看看或者做其他事情。
Java內置鎖:深度解析lock和trylock - 程序員古德
參考文檔:https://docx.iamqiang.com/jdk11/api/java.base/java/util/concurrent/locks/Lock.html#lock()
下面舉一個例子,模擬一個餐廳,其中有固定數量的座位,客戶(線程)需要獲取鎖(座位)才能在餐廳就餐,如果座位被占用,客戶將等待直到有座位可用。
創(chuàng)建一個餐廳類餐廳類Restaurant,導入java.util.concurrent.locks.Lock和java.util.concurrent.locks.ReentrantLock,如下代碼:
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Restaurant {
// 餐廳的座位,用Lock表示
private final Lock seat=new ReentrantLock();
// 客戶進入餐廳并坐下
public void enterAndSit() {
// 客戶嘗試獲取座位鎖
seat.lock();
try {
// 客戶已經坐下,這里可以執(zhí)行就餐的相關操作
System.out.println(Thread.currentThread().getName() + " 已進入餐廳并坐下。");
// 模擬就餐時間
try {
Thread.sleep(1000); // 等待1秒
} catch (InterruptedException e) {
e.printStackTrace();
}
} finally {
// 客戶離開時釋放座位鎖
seat.unlock();
System.out.println(Thread.currentThread().getName() + " 已離開餐廳。");
}
}
}
創(chuàng)建一個client類來模擬多個客戶同時嘗試進入餐廳,如下代碼:
public class RestaurantClient {
public static void main(String[] args) {
// 創(chuàng)建一個餐廳實例
Restaurant restaurant=new Restaurant();
// 模擬多個客戶線程
for (int i=0; i < 5; i++) {
new Thread(() -> {
restaurant.enterAndSit();
}, "客戶" + Thread.currentThread().getId()).start();
}
}
}
運行RestaurantClient會看到類似以下的輸出(由于線程調度的不確定性,輸出順序可能會有所不同):
客戶13 已進入餐廳并坐下。
客戶13 已離開餐廳。
客戶12 已進入餐廳并坐下。
客戶12 已離開餐廳。
客戶11 已進入餐廳并坐下。
客戶11 已離開餐廳。
客戶10 已進入餐廳并坐下。
客戶10 已離開餐廳。
客戶9 已進入餐廳并坐下。
客戶9 已離開餐廳。
從輸出中可以看到,盡管同時啟動了5個客戶線程,但它們是順序地進入餐廳并坐下的,這是因為lock()方法是阻塞的,當一個客戶獲得座位鎖時,其他客戶必須等待直到鎖被釋放,這就確保了餐廳在任何時候都不會有超過其座位數的客戶同時就餐。
參考文檔:https://docx.iamqiang.com/jdk11/api/java.base/java/util/concurrent/locks/Lock.html#tryLock()
接著模擬餐廳排隊的場景,這次使用Lock接口中的tryLock()方法,如果座位不可用,則他們可以選擇做其他事情,而不是無限期等待,先定義餐廳類Restaurant,使用ReentrantLock作為座位鎖,如下代碼:
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Restaurant {
// 餐廳的座位,用Lock表示
private final Lock seat=new ReentrantLock();
// 客戶嘗試進入餐廳并坐下,如果無法立即獲得座位則返回false
public boolean tryEnterAndSit() {
// 客戶嘗試獲取座位鎖,如果成功則進入餐廳,否則返回false
boolean acquired=seat.tryLock();
if (acquired) {
try {
// 客戶已經坐下,這里可以執(zhí)行就餐的相關操作
System.out.println(Thread.currentThread().getName() + " 已進入餐廳并坐下。");
// 模擬就餐時間
try {
Thread.sleep(1000); // 等待1秒
} catch (InterruptedException e) {
e.printStackTrace();
}
} finally {
// 客戶離開時釋放座位鎖
seat.unlock();
System.out.println(Thread.currentThread().getName() + " 已離開餐廳。");
}
} else {
// 客戶未能獲得座位
System.out.println(Thread.currentThread().getName() + " 無法進入餐廳,座位已被占用。");
}
return acquired;
}
}
創(chuàng)建一個client類來模擬多個客戶同時嘗試進入餐廳,如下代碼:
public class RestaurantClient {
public static void main(String[] args) {
// 創(chuàng)建一個餐廳實例
Restaurant restaurant=new Restaurant();
// 模擬多個客戶線程
for (int i=0; i < 5; i++) {
new Thread(() -> {
// 嘗試進入餐廳
boolean success=restaurant.tryEnterAndSit();
// 如果未能進入餐廳,則做其他事情
if (!success) {
System.out.println(Thread.currentThread().getName() + " 選擇去其他地方。");
}
}, "客戶" + (i + 1)).start();
}
}
}
運行RestaurantClient會看到類似以下的輸出(由于線程調度的不確定性,輸出順序可能會有所不同):
客戶1 已進入餐廳并坐下。
客戶2 無法進入餐廳,座位已被占用。
客戶2 選擇去其他地方。
客戶3 無法進入餐廳,座位已被占用。
客戶3 選擇去其他地方。
客戶4 無法進入餐廳,座位已被占用。
客戶4 選擇去其他地方。
客戶5 無法進入餐廳,座位已被占用。
客戶5 選擇去其他地方。
客戶1 已離開餐廳。
從輸出中可以看到,只有第一個客戶成功進入了餐廳,因為tryLock()方法是非阻塞的,當一個客戶獲得座位鎖時,其他客戶會立即得到反饋,知道座位不可用,并選擇了做其他事情,這就展示了tryLock()方法如何在避免線程長時間等待發(fā)揮作用。
Java內置鎖:深度解析lock和trylock - 程序員古德
lock方法是一種阻塞性的獲取鎖的方式,當調用一個對象的lock方法時,如果鎖當前被其他線程持有,那么當前線程將會被掛起(即阻塞),直到鎖被釋放,這種機制確保了只有一個線程能夠在同一時間訪問被鎖保護的代碼塊或資源,從而避免了并發(fā)問題,但是,它也可能導致線程長時間等待,特別是在高并發(fā)環(huán)境下,如果鎖的持有者因為某些原因(如死鎖)未能及時釋放鎖,那么其他線程可能會一直等待下去。
tryLock方法則是一種非阻塞性的獲取鎖的方式,當調用一個對象的tryLock方法時,如果鎖當前可用,那么將成功獲得鎖并繼續(xù)執(zhí)行;如果鎖被其他線程持有,那么不會被掛起,而是立即得到一個失敗的結果(通常是一個布爾值false),這種方式的好處是可以避免線程長時間等待,因為可以立即知道是否獲得了鎖,但是,這也意味著可能需要編寫更復雜的邏輯來處理未能獲得鎖的情況,例如通過重試機制或執(zhí)行備選方案等。
總結:如果希望確保線程能夠按照特定的順序訪問共享資源,并且不介意可能的等待時間,那么lock方法是一個不錯的選擇,但是,如果希望避免線程長時間等待,并且能夠處理未能立即獲得鎖的情況,那么tryLock方法可能更適合。
關注我,每天學習互聯網編程技術 - 程序員古德
ava內置鎖:深度解析StampedLock并發(fā)類 - 程序員古德
StampedLock類是一種高性能的讀寫鎖,它通過引入樂觀讀和寫鎖的優(yōu)化機制,提高了多線程環(huán)境下的并發(fā)性能,他支持三種訪問模式:悲觀讀、寫和樂觀讀,可以根據不同的業(yè)務場景選擇適合的鎖策略,相比傳統(tǒng)的讀寫鎖,StampedLock能夠更好地利用多核處理器的優(yōu)勢,減少線程間的競爭和阻塞,從而提升系統(tǒng)的吞吐量和響應速度。
官方文檔地址:https://docx.iamqiang.com/jdk11/api/java.base/java/util/concurrent/locks/StampedLock.html
Java內置鎖:深度解析StampedLock并發(fā)類
使用場景
Java內置鎖:深度解析StampedLock并發(fā)類 - 程序員古德
StampedLock是一個優(yōu)化的讀寫鎖,它在多核處理器上提供了比ReentrantReadWriteLock更高的性能,與傳統(tǒng)的讀寫鎖不同,StampedLock支持三種訪問模式:讀、寫和樂觀讀,并且這三種模式都可以相互轉換。
假設有一個在線書店系統(tǒng),其中一個關鍵功能是書籍的庫存更新,每當用戶購買書籍時,系統(tǒng)需要從庫存中減去相應的數量,同時,為了提供良好的用戶體驗,系統(tǒng)還需要實時顯示每本書的當前庫存量,以供其他用戶參考。在這個場景中,庫存更新操作(寫操作)和庫存查詢操作(讀操作)是頻繁發(fā)生的,而且,多個用戶可能同時查詢同一本書的庫存,但同一時間只有一個用戶能夠更新庫存。
可以使用StampedLock解決這個問題,如下操作:
Java內置鎖:深度解析StampedLock并發(fā)類 - 程序員古德
StampedLock 類中的 asReadLock() 方法用于獲取一個 Lock 視圖,該視圖具有與 StampedLock 的讀鎖相同的鎖定含義,可以使用返回的 Lock 對象進行讀鎖定,就像使用 ReentrantReadWriteLock 的讀鎖一樣,但是,通常建議使用 StampedLock 的其他方法來獲取讀鎖,因為它們可以提供更精細的控制和更高的性能。
下面是一個簡單的例子,演示了使用 StampedLock 類的基本使用方法,這個例子創(chuàng)建了一個簡單的計數器類,該類使用 StampedLock 來同步對內部計數器的訪問,如下代碼:
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.StampedLock;
/**
* @創(chuàng)建人 程序員古德 <br>
* @創(chuàng)建時間 2024/1/18 12:00 <br>
* @修改人 暫無 <br>
* @修改時間 暫無 <br>
* @版本歷史 暫無 <br>
*/
public class Counter {
private int count;
private final StampedLock stampedLock=new StampedLock();
// 使用 StampedLock 的 asReadLock() 方法獲取讀鎖
public void readCountWithLock() {
Lock readLock=stampedLock.asReadLock();
readLock.lock(); // 獲取讀鎖
try {
System.out.println("Current count: " + count);
} finally {
readLock.unlock(); // 釋放讀鎖
}
}
// 使用 StampedLock 的普通讀方法
public int readCountWithStamp() {
long stamp=stampedLock.tryOptimisticRead(); // 嘗試樂觀讀
int currentCount=count;
// 檢查樂觀讀后數據是否被修改
if (!stampedLock.validate(stamp)) {
// 如果數據被修改,獲取讀鎖重新讀取
stamp=stampedLock.readLock();
try {
currentCount=count;
} finally {
stampedLock.unlockRead(stamp);
}
}
return currentCount;
}
// 增加計數器的值
public void incrementCount() {
long stamp=stampedLock.writeLock(); // 獲取寫鎖
try {
count++;
} finally {
stampedLock.unlockWrite(stamp); // 釋放寫鎖
}
}
public static void main(String[] args) throws InterruptedException {
Counter counter=new Counter();
// 啟動一個線程來增加計數器的值
Thread incrementThread=new Thread(() -> {
for (int i=0; i < 5; i++) {
counter.incrementCount();
try {
Thread.sleep(100); // 休眠以模擬工作負載
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
// 啟動一個線程來讀取計數器的值(使用 Lock)
Thread readThreadWithLock=new Thread(() -> {
for (int i=0; i < 5; i++) {
counter.readCountWithLock();
try {
Thread.sleep(100); // 休眠以模擬工作負載
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
// 啟動一個線程來讀取計數器的值(使用 stamp)
Thread readThreadWithStamp=new Thread(() -> {
for (int i=0; i < 5; i++) {
System.out.println("Current count (stamp): " + counter.readCountWithStamp());
try {
Thread.sleep(100); // 休眠以模擬工作負載
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
// 啟動所有線程
incrementThread.start();
readThreadWithLock.start();
readThreadWithStamp.start();
// 等待所有線程完成
incrementThread.join();
readThreadWithLock.join();
readThreadWithStamp.join();
}
}
在上面代碼中,Counter 類有一個 count 變量,它可以通過 incrementCount 方法來增加,讀取計數器值的方法有兩種:readCountWithLock 使用 asReadLock() 方法返回的 Lock 對象進行同步,而 readCountWithStamp 則使用 StampedLock 的樂觀讀和讀鎖功能。在 main 方法中,啟動了三個線程,一個用于增加計數器的值,另外兩個用于讀取計數器的值(一個使用 Lock,另一個使用 stamp)。
asReadLock() 方法提供了普通 Lock 的方式,但通常建議直接使用 StampedLock 的其他方法(如 tryOptimisticRead、readLock、unlockRead 等),因為它們提供了更高級別的并發(fā)控制和性能優(yōu)化。
Java內置鎖:深度解析StampedLock并發(fā)類 - 程序員古德
StampedLock提供了一種高效的線程同步方式,與傳統(tǒng)的讀寫鎖相比,如:ReentrantReadWriteLock,StampedLock則在某些方面展現出了其獨特的優(yōu)勢,如下分析:
優(yōu)點:
缺點:
使用建議:
StampedLock和ReentrantReadWriteLock都是Java中用于同步的機制,它們允許多個線程同時讀取共享資源,但在寫入時要求獨占訪問,盡管它們的目的相似,但在設計、性能和適用場景上存在一些關鍵區(qū)別:
在設計上:
在性能上:
在適用場景上:
其他對比:
關注我,每天學習互聯網編程技術 - 程序員古德
END!
*請認真填寫需求信息,我們會在24小時內與您取得聯系。