Java多線程并發(fā)JUC包ReentrantLock顯示鎖的用法
Java多線程并發(fā)JUC包 ReentrantLock 顯示鎖
ReentrantLock支持以下功能:
- 支持公平和非公平的獲取鎖的方式。
- 支持可重入。
公平鎖與非公平鎖:
- 公平鎖:加鎖前先查看是否有排隊等待的線程,有的話優(yōu)先處理排在前面的線程,先來先得。
- 非公平鎖:線程加鎖時直接嘗試獲取鎖,獲取不到就自動到隊尾等待。
1 lock 和 unlock 方法說明
該demo模擬電影院的售票情況,tickets總票數(shù)。開啟了10個窗口售票,售完為止,程序代碼如下:
public class ReentrantLockDemo01 implements Runnable {
private Lock lock = new ReentrantLock();
private int tickets = 50;
@Override
public void run() {
while (true) {
// 獲取鎖
if (lock.tryLock()) {
try {
if (tickets > 0) {
TimeUnit.MILLISECONDS.sleep(100);
System.out.println(Thread.currentThread().getName() + " " + tickets--);
} else {
break;
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock(); // 釋放所
}
}
}
}
public static void main(String[] args) {
ReentrantLockDemo01 reentrantLockDemo = new ReentrantLockDemo01();
for (int i = 0; i < 10; i++) {
Thread thread = new Thread(reentrantLockDemo, "thread - " + i);
thread.start();
}
}
}輸出如下 :
thread - 0 50
thread - 7 49
thread - 4 48
thread - 7 47
thread - 7 46
thread - 7 45
thread - 7 44
thread - 7 43
thread - 7 42
thread - 7 41
thread - 7 40
thread - 7 39
thread - 7 38
thread - 7 37
thread - 7 36
thread - 7 35
thread - 7 34
thread - 7 33
thread - 7 32
thread - 7 31
thread - 7 30
thread - 5 29
thread - 5 28
thread - 5 27
thread - 6 26
thread - 6 25
thread - 7 24
thread - 7 23
thread - 7 22
thread - 7 21
thread - 5 20
thread - 5 19
thread - 5 18
thread - 7 17
thread - 2 16
thread - 2 15
thread - 2 14
thread - 2 13
thread - 1 12
thread - 1 11
thread - 1 10
thread - 1 9
thread - 1 8
thread - 1 7
thread - 1 6
thread - 1 5
thread - 1 4
thread - 1 3
thread - 1 2
thread - 1 1
2 newCondition方法
Condition的作用是對鎖進(jìn)行更精確的控制。
Condition中的 await() 方法相當(dāng)于Object的 wait() 方法,Condition中的 signal() 方法相當(dāng)于Object的 notify() 方法,Condition中的 signalAll() 相當(dāng)于Object的 notifyAll() 方法。
不同的是,Object中的 wait() , notify() , notifyAll() 方法是和”同步鎖”(synchronized關(guān)鍵字)捆綁使用的;而Condition是需要與”互斥鎖”/”共享鎖”捆綁使用的。
/**
* 生產(chǎn)者消費者
*/
public class ProducerConsumerTest {
private Lock lock = new ReentrantLock();
private Condition addCondition = lock.newCondition();
private Condition removeCondition = lock.newCondition();
private LinkedList<Integer> resources = new LinkedList<>();
private int maxSize;
public ProducerConsumerTest(int maxSize) {
this.maxSize = maxSize;
}
public class Producer implements Runnable {
private int proSize;
private Producer(int proSize) {
this.proSize = proSize;
}
@Override
public void run() {
lock.lock();
try {
for (int i = 1; i < proSize; i++) {
while (resources.size() >= maxSize) {
System.out.println("當(dāng)前倉庫已滿,等待消費...");
try {
addCondition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("已經(jīng)生產(chǎn)產(chǎn)品數(shù): " + i + "\t現(xiàn)倉儲量總量:" + resources.size());
resources.add(i);
removeCondition.signal();
}
} finally {
lock.unlock();
}
}
}
public class Consumer implements Runnable {
@Override
public void run() {
String threadName = Thread.currentThread().getName();
while (true) {
lock.lock();
try {
while (resources.size() <= 0) {
System.out.println(threadName + " 當(dāng)前倉庫沒有產(chǎn)品,請稍等...");
try {
// 進(jìn)入阻塞狀態(tài)
removeCondition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 消費數(shù)據(jù)
int size = resources.size();
for (int i = 0; i < size; i++) {
Integer remove = resources.remove();
System.out.println(threadName + " 當(dāng)前消費產(chǎn)品編號為:" + remove);
}
// 喚醒生產(chǎn)者
addCondition.signal();
} finally {
lock.unlock();
}
}
}
}
public static void main(String[] args) throws InterruptedException {
ProducerConsumerTest producerConsumerTest = new ProducerConsumerTest(10);
Producer producer = producerConsumerTest.new Producer(100);
Consumer consumer = producerConsumerTest.new Consumer();
final Thread producerThread = new Thread(producer, "producer");
final Thread consumerThread = new Thread(consumer, "consumer");
producerThread.start();
TimeUnit.SECONDS.sleep(2);
consumerThread.start();
}
}總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
spring security登錄成功后通過Principal獲取名返回空問題
這篇文章主要介紹了spring security登錄成功后通過Principal獲取名返回空問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-03-03
關(guān)于Java?中?Future?的?get?方法超時問題
這篇文章主要介紹了Java?中?Future?的?get?方法超時,最常見的理解就是,“超時以后,當(dāng)前線程繼續(xù)執(zhí)行,線程池里的對應(yīng)線程中斷”,真的是這樣嗎?本文給大家詳細(xì)介紹,需要的朋友參考下吧2022-06-06
Java使用freemarker實現(xiàn)word下載方式
文章介紹了如何使用FreeMarker實現(xiàn)Word文件下載,包括引用依賴、創(chuàng)建Word模板、將Word文件存為XML格式、更改后綴為FTL模板、處理圖片和代碼實現(xiàn)2025-02-02
spring?@Transactional注解中常用參數(shù)詳解
這篇文章主要介紹了spring?@Transactional注解中常用參數(shù)詳解,事物注解方式:?@Transactional,本文結(jié)合實例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2024-02-02
通過springboot發(fā)布WebService接口并調(diào)用方式
Spring Boot集成CXF需注意版本對應(yīng),配置注解并發(fā)布服務(wù),通過WSDL驗證,結(jié)合Controller和Swagger測試,CXF支持SOAP、REST等服務(wù),提供代碼與合同優(yōu)先開發(fā)模式2025-09-09
淺談HttpClient、okhttp和RestTemplate的區(qū)別
這篇文章主要介紹了HttpClient、okhttp和RestTemplate的區(qū)別,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-06-06

