Java線程通信中關(guān)于生產(chǎn)者與消費者案例分析
相關(guān)方法:
wait():一旦執(zhí)行此方法,當(dāng)前線程就進(jìn)入阻塞狀態(tài),并釋放同步監(jiān)視器。
notify():一旦執(zhí)行此方法,就會喚醒被wait的一個線程,如果有多個線程被wait,就喚醒優(yōu)先級高的那個。
notifyAll():一旦執(zhí)行此方法,就會喚醒所有被wait的線程。
說明:
1.wait(),notify(),notifyAll()三個方法必須使用在同步代碼塊或同步方法中。
2.wait(),notify(),notifyAll()三個方法的調(diào)用者必須是同步代碼塊或同步方法中的同步監(jiān)視器。
否則,會出現(xiàn)IllegalMonitorStateException異常
3.wait(),notify(),notifyAll()三個方法是定義在java.lang.Object類中。
線程通信的例子:使用兩個線程打印1-100.線程1,線程2 交替打印
class Number implements Runnable{
private int number = 1;
@Override
public void run() {
while(true){
synchronized (this) {
notify();
if(number <= 100){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":" + number);
number++;
try {
//使得調(diào)用如下wait()方法的線程進(jìn)入阻塞狀態(tài)
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}else{
break;
}
}
}
}
}
public class CommunicationTest {
public static void main(String[] args) {
Number number = new Number();
Thread t1 = new Thread(number);
Thread t2 = new Thread(number);
t1.setName("線程1");
t2.setName("線程2");
t1.start();
t2.start();
}
}
經(jīng)典例題:生產(chǎn)者/消費者問題
生產(chǎn)者(Productor)將產(chǎn)品交給店員(Clerk),而消費者(Customer)從店員處取走產(chǎn)品店員一次只能持有固定數(shù)量的產(chǎn)品(比如:20),如果生產(chǎn)者試圖生產(chǎn)更多的產(chǎn)品,店員會叫生產(chǎn)者停一下,如果店中有空位放產(chǎn)品了再通知生產(chǎn)者繼續(xù)生產(chǎn),如果店中沒有產(chǎn)品了,店員會告訴消費者等一下,如果店中有產(chǎn)品了再通知消費者來取走產(chǎn)品。
這里可能出現(xiàn)兩個問題:
>生產(chǎn)者比消費者快時,消費者會漏掉一些數(shù)據(jù)沒有取到。
>消費者比生產(chǎn)者塊時,消費者會取相同的數(shù)據(jù)。
分析:
- 是否是多線程問題?是,生產(chǎn)者線程,消費者線程
- 是否有共享數(shù)據(jù)?有,店員(或產(chǎn)品)
- 如何解決線程安全問題?同步機(jī)制,有三種方法
- 是否涉及線程的通信?是
class Clerk{
private int productCount = 0;
//生產(chǎn)產(chǎn)品
public synchronized void produceProduct() {
if(productCount < 20){
productCount++;
System.out.println(Thread.currentThread().getName() + ":開始生產(chǎn)第" + productCount + "個產(chǎn)品");
notify();
}else{
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//消費產(chǎn)品
public synchronized void consumeProduct() {
if(productCount > 0){
System.out.println(Thread.currentThread().getName() + ":開始消費第" + productCount + "個產(chǎn)品");
productCount--;
notify();
}else{
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Producer extends Thread{//生產(chǎn)者
private Clerk clerk;
public Producer(Clerk clerk){
this.clerk = clerk;
}
@Override
public void run() {
System.out.println(getName() + ":開始生產(chǎn)產(chǎn)品.....");
while(true){
try {
sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
clerk.produceProduct();
}
}
}
class Consumer extends Thread{//消費者
private Clerk clerk;
public Consumer(Clerk clerk){
this.clerk = clerk;
}
@Override
public void run() {
System.out.println(getName() + ":開始消費產(chǎn)品.....");
while(true){
try {
sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
clerk.consumeProduct();
}
}
}
public class ProductTest {
public static void main(String[] args) {
Clerk clerk = new Clerk();
Producer p1 = new Producer(clerk);
p1.setName("生產(chǎn)者1");
Consumer c1 = new Consumer(clerk);
c1.setName("消費者1");
Consumer c2 = new Consumer(clerk);
c2.setName("消費者2");
p1.start();
c1.start();
c2.start();
}
}
sleep()和wait()的異同?
1.相同點:一旦執(zhí)行方法,都可以使得當(dāng)前的線程進(jìn)入阻塞狀態(tài)。
2.不同點:
1)兩個方法聲明的位置不同,Thread類中聲明sleep(),Object類中聲明wait()
2)調(diào)用的要求不同:sleep()可以在任何需要的場景下調(diào)用。wait()必須使用在同步代碼塊或同步方 法中
3)關(guān)于是否釋放同步監(jiān)視器:如果兩個方法都使用在同步代碼塊或同步方法中,sleep()不會釋放 鎖,wait()會釋放鎖
到此這篇關(guān)于Java線程通信中關(guān)于生產(chǎn)者與消費者案例分析的文章就介紹到這了,更多相關(guān)Java線程通信內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java異步調(diào)用轉(zhuǎn)同步方法實例詳解
這篇文章主要介紹了Java異步調(diào)用轉(zhuǎn)同步方法實例詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-06-06
Java基于socket服務(wù)實現(xiàn)UDP協(xié)議的方法
這篇文章主要介紹了Java基于socket服務(wù)實現(xiàn)UDP協(xié)議的方法,通過兩個簡單實例分析了java通過socket實現(xiàn)UDP發(fā)送與接收的技巧,需要的朋友可以參考下2015-05-05
空指針HttpSession異常之SpringBoot集成WebSocket的方法
文章介紹了在Spring?Boot中集成WebSocket時遇到的HttpSession為空的問題,并探討了三種解決方法,方法一涉及域名配置,方法二通過監(jiān)聽創(chuàng)建Session,而方法三是從request中獲取session并存入數(shù)據(jù),感興趣的朋友一起看看吧2025-01-01
淺談Spring中@Transactional事務(wù)回滾及示例(附源碼)
本篇文章主要介紹了淺談Spring中@Transactional事務(wù)回滾及示例(附源碼),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-12-12
springboot如何為web層添加統(tǒng)一請求前綴
這篇文章主要介紹了springboot如何為web層添加統(tǒng)一請求前綴,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-02-02

