Java多種方式實現(xiàn)生產者消費者模式
實現(xiàn)需求:兩個線程交替打印1,0,打印10輪
java多線程口訣:
- 高內聚,低耦合
- 線程操作資源類
- 判斷干活通知
- 防止虛假喚醒
方式一:使用synchronized和Object的wait和notifyAll方法
wait:使當前線程阻塞
notify,notifyAll喚醒當前線程
/**
* 兩個線程交替打印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();
}
}
輸出結果
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();
}
}
輸出結果
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,能夠精確喚醒
需求:三個線程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();
}
}
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
springboot使用JdbcTemplate完成對數(shù)據(jù)庫的增刪改查功能
這篇文章主要介紹了springboot使用JdbcTemplate完成對數(shù)據(jù)庫的增刪改查功能,需要的朋友可以參考下2017-12-12
實踐講解SpringBoot自定義初始化Bean+HashMap優(yōu)化策略模式
本篇講解了SpringBoot自定義初始化Bean+HashMap優(yōu)化策略模式,通過實踐的方式更通俗易懂,對此不了解的同學跟著小編往下看吧2021-09-09
Java interrupt()方法使用注意_動力節(jié)點Java學院整理
這篇文章主要介紹了Java interrupt()方法使用注意_動力節(jié)點Java學院整理,需要的朋友可以參考下2017-05-05
Windows系統(tǒng)下Eclipse搭建ESP32編譯環(huán)境及安裝過程
Ecppse 使用了 ESP-IDF 中的 Makefile 支持。這意味著您需要從創(chuàng)建 ESP-IDF 項目開始。您可以使用 github 中的 idf-template 項目,接下來通過本文給大家介紹Windows系統(tǒng)下Eclipse搭建ESP32編譯環(huán)境及安裝過程,感興趣的朋友一起看看吧2021-10-10

