java自學-執行緒通訊(生產者和消費者問題)(同步塊實現)
阿新 • • 發佈:2018-11-09
注意事項:
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();
}
}