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