1. 程式人生 > >java自學-執行緒通訊(生產者和消費者問題)(同步塊實現)

java自學-執行緒通訊(生產者和消費者問題)(同步塊實現)

注意事項:

1、sleep()和wait()區別:

      sleep:進入【普通】阻塞佇列;不釋放鎖;可以在任何地方使用。

      wait:進入【該監視器】阻塞佇列,是與sleep不同的阻塞佇列;釋放鎖;wait()只能在【監視器同步塊中使用】,不然會報錯並且進入的。

2、wait前面加product物件,product.wait(),不然預設this.wait(),會導致進入不同的佇列。

3、wait(),notify(),notify()必須是同一個同步監視器的,一定要在同步塊內。

4、wait()還有一種使用方法wait(time),wait(time)時間到了就喚醒執行緒,不需要notify()。

5、notify()喚醒該監視器的【任意一個】執行緒,notifyAll()喚醒該監視器的所有執行緒。

6、yield()和sleep()區別如下圖。

 

生產者執行緒; 

package ProduceConsum;

public class Produce implements Runnable{
	private Product product=null;
	
	public Produce(Product product) {
		super();
		this.product = product;
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub

	}

	@Override
	public void run() {
		int i=0;
		while(true) {
			synchronized(product) {//生產者和消費者都必須加鎖,並且必須加同一把鎖
				if(product.flag) {
					try {
						product.wait();
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				if((i&1)==0) {
					product.setName("饅頭");
					try {
						Thread.sleep(1);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					product.setColor("白色");
					System.out.println("生產者在生產商品  "+product.getName()+" "+product.getColor());
				}else {
					product.setName("玉米");
					try {
						Thread.sleep(1);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					product.setColor("紅色");
					System.out.println("生產者在生產商品  "+product.getName()+" "+product.getColor());
				}
				i++;
				product.flag=true;
				product.notify();
			}
			
		}
	}

}

消費者執行緒;

package ProduceConsum;

public class Consum implements Runnable{
	private Product product=null;
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub

	}

	@Override
	public void run() {
		while(true) {
			
			synchronized(product){
				if(!product.flag) {
					try {
						product.wait();
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				System.out.println("消費者在消費產品"+product.getName()+product.getColor());
				product.flag=false;
				product.notify();
			}
		}
		
	}

	public Consum(Product product) {
		super();
		this.product = product;
	}

}

產品類;

package ProduceConsum;

public class Product {
	private String name;
	private String color;
	public boolean flag=false;
	public String getName(){
		return name;
	}
	
	public void setName(String name) {
		this.name = name;
	}

	public void setColor(String color) {
		this.color = color;
	}

	public String getColor() {
		return color;
	}
	
	public Product() {
		super();
	}
	public Product(String name, String color) {
		super();
		this.name = name;
		this.color = color;
	}
	
	@Override
	public String toString() {
		return "product [name=" + name + ", color=" + color + "]";
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub

	}

}

主程式碼: 

package ProduceConsum;

public class test {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Object obj;
		Product product=new Product();
		
		Runnable p=new Produce(product);
		Thread th1=new Thread(p);
		
		Runnable c=new Consum(product);
		Thread th2=new Thread(c);
		
		th1.start();
		th2.start();
	}

}

二、同步方法實現:

生產者執行緒:

package ProduceConsum.copy1;

public class Produce implements Runnable{
	private Product product=null;
	
	public Produce(Product product) {
		super();
		this.product = product;
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub

	}

	@Override
	public void run() {
		int i=0;
		while(true) {
			if((i&1)==0) {
				product.producing("饅頭", "白色");
			}else {
				product.producing("玉米", "紅色");
			}
			i++;
		}
	}

}

 

 消費者執行緒:

package ProduceConsum.copy1;

public class Consum implements Runnable{
	private Product product=null;
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub

	}

	@Override
	public void run() {
		while(true) {
			product.consuming();
		}
	}

	public Consum(Product product) {
		super();
		this.product = product;
	}

}

產品類(內含同步方法):

package ProduceConsum.copy1;

public class Product {
	private String name;
	private String color;
	public boolean flag=false;
	
	public synchronized void producing(String name,String color) {
		this.name=name;
		this.color=color;
		if(flag) {
			try {
				wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		try {
			Thread.sleep(1);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("生產者在生產商品  "+name+" "+color);
		
		this.flag=true;
		this.notify();
	}

	public synchronized void consuming() {
		if(!flag) {
			try {
				wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		System.out.println("消費者在消費產品"+name+color);
		flag=false;
		notify();
	}

}

主方法:

package ProduceConsum.copy1;

public class test {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Object obj;
		Product product=new Product();
		
		Runnable p=new Produce(product);
		Thread th1=new Thread(p);
		
		Runnable c=new Consum(product);
		Thread th2=new Thread(c);
		
		th1.start();
		th2.start();
	}

}