Java多種方式實(shí)現(xiàn)生產(chǎn)者消費(fèi)者模式
實(shí)現(xiàn)需求:兩個(gè)線程交替打印1,0,打印10輪
java多線程口訣:
- 高內(nèi)聚,低耦合
- 線程操作資源類
- 判斷干活通知
- 防止虛假喚醒
方式一:使用synchronized和Object的wait和notifyAll方法
wait:使當(dāng)前線程阻塞
notify,notifyAll喚醒當(dāng)前線程
/**
* 兩個(gè)線程交替打印1,0 打印10輪
*
* @author Administrator
* @version 1.0 2020年7月12日
* @see ProdConsumerDemo1
* @since 1.0
*
*/
class ShareData1 {
public int number = 0;
public synchronized void increment() throws Exception {
while (number != 0) {
this.wait();
}
number++;
System.out.println(Thread.currentThread().getName() + " " + number);
this.notifyAll();
}
public synchronized void decrement() throws InterruptedException {
while (number != 1) {
this.wait();
}
number--;
System.out.println(Thread.currentThread().getName() + " " + number);
this.notifyAll();
}
}
public class ProdConsumerDemo1 {
public static void main(String[] args) {
ShareData1 shareData = new ShareData1();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
shareData.increment();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}, "A").start();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
shareData.decrement();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}, "B").start();
}
}
輸出結(jié)果
A 1 B 0 A 1 B 0 A 1 B 0 A 1 B 0 A 1 B 0 A 1 B 0 A 1 B 0 A 1 B 0 A 1 B 0 A 1 B 0
方式二:使用jdk1.8的Lock和Condition
class ShareData2 {
private int number = 0;
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
public void increment() throws Exception {
lock.lock();
try {
while (number != 0) {
condition.await();
}
number++;
System.out.println(Thread.currentThread().getName() + " " + number);
condition.signalAll();
} finally {
lock.unlock();
}
}
public void decrement() throws InterruptedException {
lock.lock();
try {
while (number != 1) {
condition.await();
}
number--;
System.out.println(Thread.currentThread().getName() + " " + number);
condition.signalAll();
} finally {
// TODO: handle finally clause
lock.unlock();
}
}
}
public class ProdConsumerDemo2 {
public static void main(String[] args) {
ShareData2 shareData = new ShareData2();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
shareData.increment();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}, "A").start();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
shareData.decrement();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}, "B").start();
}
}
輸出結(jié)果
A 1 B 0 A 1 B 0 A 1 B 0 A 1 B 0 A 1 B 0 A 1 B 0 A 1 B 0 A 1 B 0 A 1 B 0 A 1 B 0
主要是熟悉Lock和Condition的使用
Lock和Condition相比于synchronized,能夠精確喚醒
需求:三個(gè)線程A,B,C順序打印,A打印5次,B打印10次,C打印15次,10輪
class ShareData3 {
private int number = 1;
private Lock lock = new ReentrantLock();
private Condition c1 = lock.newCondition();
private Condition c2 = lock.newCondition();
private Condition c3 = lock.newCondition();
public void print5() throws Exception {
lock.lock();
try {
while (number != 1) {
c1.await();
}
number = 2;
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + " " + i);
}
c2.signalAll();
} finally {
// TODO: handle finally clause
lock.unlock();
}
}
public void print10() throws InterruptedException {
lock.lock();
try {
while (number != 2) {
c2.await();
}
number=3;
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + " " + i);
}
c3.signalAll();
} finally {
// TODO: handle finally clause
lock.unlock();
}
}
public void print15() throws InterruptedException {
lock.lock();
try {
while (number != 3) {
c3.await();
}
number = 1;
for (int i = 0; i < 15; i++) {
System.out.println(Thread.currentThread().getName() + " " + i);
}
c1.signalAll();
} finally {
// TODO: handle finally clause
lock.unlock();
}
}
}
public class ProdConsumerDemo3 {
public static void main(String[] args) {
ShareData3 shareData3 = new ShareData3();
new Thread(() -> {
try {
for (int i = 0; i < 10; i++) {
shareData3.print5();
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}, "A").start();
new Thread(() -> {
try {
for (int i = 0; i < 10; i++) {
shareData3.print10();
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}, "B").start();
new Thread(() -> {
try {
for (int i = 0; i < 10; i++) {
shareData3.print15();
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}, "C").start();
}
}
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
java selenium教程環(huán)境搭建基于Maven
本文主要介紹Java selenium 環(huán)境的安裝,這里介紹了基于Maven的環(huán)境搭建,有需要的小伙伴可以參考下2016-08-08
使用Java代碼進(jìn)行因數(shù)分解和求最小公倍數(shù)的示例
這篇文章主要介紹了使用Java代碼進(jìn)行因數(shù)分解和求最小公倍數(shù)的示例,都是基于最基礎(chǔ)的算法原理實(shí)現(xiàn),需要的朋友可以參考下2015-11-11
Java組件commons fileupload實(shí)現(xiàn)文件上傳功能
這篇文章主要為大家詳細(xì)介紹了Java組件commons fileupload實(shí)現(xiàn)文件上傳功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-10-10
Spring Security注冊過濾器注意事項(xiàng)詳解
前兩天和小伙伴聊了 Spring Security+JWT 實(shí)現(xiàn)無狀態(tài)登錄,然后有小伙伴反饋了一個(gè)問題,感覺這是一個(gè)我們平時(shí)寫代碼容易忽略的問題,所以本文給大家介紹了Spring Security注冊過濾器注意事項(xiàng),需要的朋友可以參考下2024-06-06
Spring Boot中自定義注解結(jié)合AOP實(shí)現(xiàn)主備庫切換問題
這篇文章主要介紹了Spring Boot中自定義注解+AOP實(shí)現(xiàn)主備庫切換的相關(guān)知識,本篇文章的場景是做調(diào)度中心和監(jiān)控中心時(shí)的需求,后端使用TDDL實(shí)現(xiàn)分表分庫,需要的朋友可以參考下2019-08-08
SpringBoot時(shí)區(qū)問題解決以及徹底解決時(shí)差問題
這篇文章主要給大家介紹了關(guān)于SpringBoot時(shí)區(qū)問題解決以及徹底解決時(shí)差問題的相關(guān)資料,spring?boot作為微服務(wù)簡易架構(gòu),擁有其自身的特點(diǎn),快速搭建架構(gòu),簡單快捷,需要的朋友可以參考下2023-08-08
SpringBoot3.x打包Docker容器的實(shí)現(xiàn)
這篇文章主要介紹了SpringBoot3.x打包Docker容器的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-11-11

