思想:
1、生產者在while回圈里不停地生產“產品”,每生產一個,就交給店員,店員就得到一個產品
2、消費者在while回圈里不停地消費產品,每消費一個,店員就移走一個產品
3、店員手里的產品少于20個,就從生產者那里拿走產品,等于20個,就停止從生產者那里拿走產品
4、店員手里的產品多于0個,就讓消費者消費產品,等于0個,就停止讓消費者消費產品
生產者:
生產者在while回圈里不停地生產“產品”,每生產一個,就交給店員,店員就得到一個產品
//生產者
class Producter implements Runnable{
Clerk clerk;
Producter(Clerk clerk){
this.clerk=clerk;
}
@Override
public void run() {
while (true){
//此處可加sleep,讓生產者生產的慢一點
clerk.getProduce();//生產者不停地生產產品,生產一個,就交給店員,店員就get一個
}
}
}
消費者:
消費者在while回圈里不停地消費產品,每消費一個,店員就移走一個產品
//消費者
class Consummer implements Runnable{
Clerk clerk;
Consummer(Clerk clerk){
this.clerk=clerk;
}
@Override
public void run() {
while (true){
//此處可加sleep,讓消費者消費的慢一些
clerk.removeProduce();//消費者不停地消費產品,消費一個,店員處就remove一個
}
}
}
店員:
店員手里的產品少于20個,就從生產者那里拿走產品,等于20個,就停止從生產者那里拿走產品
店員手里的產品多于0個,就讓消費者消費產品,等于0個,就停止讓消費者消費產品
//店員
class Clerk{
public int producenumber;//店員手里產品的數量
public synchronized void getProduce() {//鎖是clerk,反復執行的實際上是該方法和removeProduce方法
if(producenumber<20){//店員手里產品數量少于20個,就從生產者那里拿過來一個
producenumber++;
System.out.println(Thread.currentThread().getName()+"生產了第"+producenumber+"個產品");
notify();//已經從生產者那里拿過來一個產品了,說明手里肯定是有產品的,店員可以讓消費者拿走產品了
}else{
try {
wait();//店員手里產品數量多于20個,停止從生產者那里拿走產品
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
}
}
public synchronized void removeProduce(){//鎖是clerk,相當于四個執行緒一個一個的執行
if(producenumber>0){//店員手里產品數量多余0個,就讓消費者拿走產品
System.out.println(Thread.currentThread().getName()+"消費了第"+producenumber+"個產品");
producenumber--;
notify();//已經讓消費者拿走了一個產品,說明柜臺肯定有位置放產品,店員可以從生產者那里取產品了
}else{
try {
wait();//店員手里產品數量少于0個,停止讓消費者拿走產品
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
}
}
}
測驗類:
public class ThreadCommunicationTest {
public static void main(String[] args) {
Clerk clerk=new Clerk();
Producter p=new Producter(clerk);
Thread tp1=new Thread(p);
tp1.setName("生產者1");
tp1.start();
Thread tp2=new Thread(p);
tp2.setName("生產者2");
tp2.start();
Consummer c=new Consummer(clerk);
Thread tc1=new Thread(c);
tc1.setName("消費者1");
tc1.start();
Thread tc2=new Thread(c);
tc2.setName("消費者2");
tc2.start();
}
}
Attention:
一共有四個執行緒:生產者1、生產者2、消費者1、消費者2
生產者1和生產者2執行緒開啟后,呼叫Producter類里的run方法,又在run方法里呼叫Clerk類里的getProduce方法
相當于生產者1和生產者2反復執行的是getProduce方法
生產者1和生產者2執行緒開啟后,呼叫PConsummer類里的run方法,又在run方法里呼叫Clerk類里的removeProduce方法
相當于消費者1和消費者2反復執行的是removeProduce方法
而getProduce方法和removeProduce方法都是同步方法,它們都在Clerk類中定義,而Clerk類從始至終只有一個物件,所以兩個同步方法的鎖是同一把,即Clerk類的實體物件clerk
意味著在兩個方法中,四個執行緒只能一個一個的執行,因此執行緒安全
執行截圖:

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/423273.html
標籤:其他
