帮你更好的理解多线程,notify和notifyAll,阻塞队列
package com.wxt.func.pv.noblokclist;
/**
* 驱动程序
* @author dragon
*
*/
public class App {
public static void main(String[] args) {
BreadShop shop = new BreadShop(2);
BreadFactory factory = new BreadFactory(shop);
Customer c = new Customer("消费者1",shop);
Customer c1 = new Customer("消费者2",shop);
Customer c2 = new Customer("消费者3",shop);
Customer c3 = new Customer("消费者4",shop);
factory.create();
c.buyBread();
c1.buyBread();
c2.buyBread();
c3.buyBread();
}
}
package com.wxt.func.pv.noblokclist;
/**
* 面包模型
* @author coffee
*
*/
public class Bread {
private String name;
private String color;
private String memo;
public Bread(String name, String color) {
this(name,color,"");
};
public Bread(String name, String color, String memo) {
this.name = name;
this.color = color;
this.memo = memo;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public String getMemo() {
return memo;
}
public void setMemo(String memo) {
this.memo = memo;
};
public String toString(){
return "{name:"+this.name+",color:"+this.color+",memo:"+this.memo+"}";
}
}
package com.wxt.func.pv.noblokclist;
import org.apache.log4j.Logger;
/**
* 面包加工厂
* @author coffee
*
*/
public class BreadFactory extends Thread{
private BreadShop breadShop;
String[] colors = new String[]{"黑死","红色","白色"};
public BreadFactory(BreadShop breadShop){
this.breadShop = breadShop;
this.setName("面包制造工厂");
}
public synchronized void create(){
this.start();
}
/**
* 不断的生产面包
*/
public void run(){
Bread bread = null;
int index = 1;
String color = "";
while(true){
color = colors[index%3];
bread = new Bread(index+"号面包",color);
System.out.println("【"+Thread.currentThread().getName()+"】开始生产:"+"["+bread.getName()+","+bread.getColor()+"]");
try {
this.breadShop.storeBread(bread);
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
index++;
}
}
}
package com.wxt.func.pv.noblokclist;
import java.util.ArrayList;
import java.util.List;
import org.apache.log4j.Logger;
/**
* 面包直销店(卖面包的商店)
* @author dragon
*
*/
public class BreadShop{
private List<Bread> breads;
private int size;
public BreadShop(int size){
breads = new ArrayList<Bread>(size);
this.size = size;
}
/**
* 从面包加工厂购入面包
* @param bread
* @throws InterruptedException
*/
public synchronized void storeBread(Bread bread) throws InterruptedException{
if(this.breads.size() == this.size){
wait();
}
if(this.breads.size() == 0){
/*
* 这里使用Notify,java多线程机制会从等待的资源释放的(消费者线程)当中选择其一,
* 从而通知此消费者线程,开始消费。
* 如果使用NotifyAll那么所有消费者线程都被通知
* 则会导致 面包数量不够,从而导致index=0,队列没有办法romove(0);
*/
notify();
}
this.breads.add(bread);
System.out.println("【面包零售商店】目前共有:"+this.breadCnt()+"个面包"+this.breads.toString());
}
/**
* 给消费者销售面包
* @return
*/
public synchronized Bread sellBread(){
System.out.println("【面包零售商店】目前共有:"+this.breadCnt()+"个面包"+this.breads.toString());
if(this.breads.size() == 0 ){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/*
* 如果面包制造工厂,将每次制造的一个新面包放入面包直营店,使用notifyAll方式,
* 那么等待时间需要持续,由于消费者线程抢占资源,只能有一个现场获取放到队列的一个新资源(新面包)
* 致使更多的消费者线程无法消费,所以其它消费者线程必须一直等待,如果不然,则会无法消费(not Find Index 0)
while(this.breads.size() == 0 ){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
*/
if(this.size == this.breads.size()){
notifyAll();
}
Bread bread = this.breads.get(0);
this.breads.remove(0);
return bread;
}
public synchronized int breadCnt(){
return this.breads.size();
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
}
package com.wxt.func.pv.noblokclist;
import org.apache.log4j.Logger;
/**
* 消费者(吃面包的人)
* @author dragon
*
*/
public class Customer extends Thread{
private BreadShop breadShop;
public Customer(){
}
public Customer(String name,BreadShop breadShop){
this.breadShop = breadShop;
this.setName(name);
}
public void buyBread(){
this.start();
}
/**
* 消费者消费面包
*/
public void run(){
System.out.println("【"+Thread.currentThread().getName()+"】消费准备");
Bread bread = this.breadShop.sellBread();
try {
if(bread == null){
System.out.println("【"+Thread.currentThread().getName()+"】消费失败");
}else{
System.out.println("【"+Thread.currentThread().getName()+"】消费成功:"+"["+bread.getName()+","+bread.getColor()+"]面包");
}
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}