实例实现:生产者生产两种商品,消费者取走两种商品
产生的问题及解决:
数据错乱---->线程同步
重复生产和重复取------>线程间的通信
线程间通信的方法
wait():调用了 wait()方法的线程进入等待池进行等待,等待池中的线程不去竞争对象锁,直到其它的线程通知,才会进入锁池
notify():随机唤醒一个在该对象上等待的线程,被唤醒的线程进行锁池,开始竞争该对锁上的锁
notifyAll():唤醒所有在该对象上等待的线程优先级高的线程有可能先竞争到对象锁只能在同步方法和同步代码块中使用
商品类,可以设置商品名称和品牌,有存入和取走方法
1 public class Goods { 2 private String name;//名称 3 private String brand;//品牌 4 private boolean isFlag;//用于标识是否有商品 ,假设为true时代表有商品,false时代表没有商品 5 public String getName() { 6 return name; 7 } 8 public void setName(String name) { 9 this.name = name; 10 } 11 public String getBrand() { 12 return brand; 13 } 14 public void setBrand(String brand) { 15 this.brand = brand; 16 } 17 public Goods(String name, String brand) { 18 super(); 19 this.name = name; 20 this.brand = brand; 21 } 22 public Goods() { 23 super(); 24 } 25 //编写一个赋值的方法 同步监视器为Goods类的对象 26 public synchronized void set(String name,String brand){ 27 if(isFlag){//相当于isFlag==true 28 try { 29 super.wait();//生产者线程等待 30 } catch (InterruptedException e) { 31 // TODO Auto-generated catch block 32 e.printStackTrace(); 33 } 34 } //当生产者线程被唤醒后从wait()之后的代码开始执行 35 //生产商品 36 this.setName(name); 37 try { 38 Thread.sleep(300); 39 } catch (InterruptedException e) { 40 // TODO Auto-generated catch block 41 e.printStackTrace(); 42 } 43 this.setBrand(brand); 44 System.out.println("-------生产者线程生产了-------"+this.getBrand()+"-------"+this.getName()); 45 //通知消费者 46 super.notify(); 47 isFlag=true; 48 } 49 //编写一个取值的方法 50 public synchronized void get(){ 51 if(!isFlag){ // 相不于isFlag==false 52 try { 53 super.wait(); 54 } catch (InterruptedException e) { 55 // TODO Auto-generated catch block 56 e.printStackTrace(); 57 }//消费者等待 58 }//消费者线程被唤醒后从wait()之后开始执行 59 60 System.out.println("消费者线程取走了------"+this.getBrand()+"--------"+this.getName()); 61 super.notify();//通知生产者线程 62 isFlag=false;//没有商品 63 } 64 65 }
生产者线程类,调用商品类的set()设置生产哪种商品
1 public class Producter implements Runnable{ 2 private Goods goods; 3 public Producter(Goods goods){ 4 this.goods=goods; 5 } 6 @Override 7 public void run() { 8 //生产商品 9 for(int i=0;i<10;i++){ 10 if(i%2!=0){//奇数 11 goods.set("小馒头", "旺仔");//调用商品类的同步方法 12 }else{ 13 goods.set("矿泉水", "娃哈哈"); 14 } 15 16 } 17 } 18 19 }
消费者线程类,调用商品类的get()取走商品
1 public class Customer implements Runnable { 2 private Goods goods; 3 public Customer(Goods goods){ 4 this.goods=goods; 5 } 6 public void run() { 7 for(int i=0;i<10;i++){ 8 goods.get();//调用商品类中的取值的方法 9 } 10 11 }; 12 }
启动类
1 public class Test { 2 public static void main(String[] args) { 3 //创建共享资源对象 4 Goods g=new Goods(); 5 //创建生产者线程 6 Producter p=new Producter(g); 7 //创建生产者线程 8 Customer c=new Customer(g); 9 new Thread(p).start(); 10 new Thread(c).start(); 11 } 12 }
------------------------------------------------------------------------------------
结果截图
来源:https://www.cnblogs.com/bfcs/p/10702219.html