对这个问题更深一点理解是,每一个线程都在竞争这个类的实例的monitor对象。
java会为每个object对象分配一个monitor,当某个对象的同步方法(synchronized methods )被多个线程调用时,该对象的monitor将负责处理这些访问的并发独占要求。
任何时刻,对一个指定object对象的某同步方法只能由一个线程来调用。java对象的monitor是跟随object实例来使用的,而不是跟随程序代码。两个线程可以同时执行相同的同步方法,比如:一个类的同步方法是xMethod(),有a,b两个对象实例,一个线程执行a.xMethod(),另一个线程执行b.xMethod(). 互不冲突。下面是单生产者单消费者的实例

1 /* 2 * 生产者消费者 3 * 分类: 4 * 单生产者单消费者 5 * 多生产者的消费者 6 * 7 * 8 * 单生产者单消费者: 9 * 两个线程:生产线程,消费线程 10 * 两个任务:生产任务,消费任务 11 * 一份数据 12 */ 13 public class Demo4 { 14 public static void main(String[] args) { 15 //1.准备数据 16 Product product = new Product(); 17 //2.创建生产消费任务 18 Producer producer = new Producer(product); 19 Consumer consumer = new Consumer(product); 20 //3.创建生产消费线程 21 Thread thread1 = new Thread(producer); 22 Thread thread2 = new Thread(consumer); 23 //4.开启线程 24 thread1.start(); 25 thread2.start(); 26 } 27 } 28 29 //数据类 30 class Product{ 31 String name; 32 double price; 33 int count; 34 35 //标识 36 boolean flag; 37 38 //准备生产 39 public synchronized void setProduce(String name,double price) { 40 if (flag == true) { 41 try { 42 wait(); 43 } catch (InterruptedException e) { 44 // TODO Auto-generated catch block 45 e.printStackTrace(); 46 } 47 } 48 49 this.name = name; 50 this.price = price; 51 52 System.out.println(Thread.currentThread().getName()+" 生产了:"+name+" 产品的数量:"+count+" 产品的价格:"+price); 53 54 count++; 55 56 flag = !flag; 57 58 //唤醒消费线程 59 notify(); 60 } 61 //准备消费 62 public synchronized void consume() { 63 if (flag == false) { 64 try { 65 wait(); 66 } catch (InterruptedException e) { 67 // TODO Auto-generated catch block 68 e.printStackTrace(); 69 } 70 } 71 72 System.out.println(Thread.currentThread().getName()+" 消费了:"+name+" 产品的数量:"+count+" 产品的价格:"+price); 73 74 flag = !flag; 75 76 //唤醒生产线程 77 notify(); 78 } 79 } 80 //生产任务 81 class Producer implements Runnable{ 82 Product product; 83 84 public Producer(Product product) { 85 super(); 86 this.product = product; 87 } 88 89 public void run() { 90 while (true) { 91 product.setProduce("bingbing", 10); 92 } 93 } 94 } 95 //消费任务 96 97 class Consumer implements Runnable{ 98 Product product; 99 100 public Consumer(Product product) { 101 super(); 102 this.product = product; 103 } 104 105 public void run() { 106 while (true) { 107 product.consume(); 108 } 109 } 110 }
多生产者多消费者:
* 两个生产线程,两个消费线程
* 两个任务:生产任务,消费任务
* 一份数据
*
* 生产任务与消费任务共用一个数据--产品类
*
* 要求:最终也要实现一次生产一次消费
*
*错误描述:当有两个生产线程,两个消费线程同时存在的时候,有可能出现生产一次,消费多次或者生产多次消费一次的情况.
*原因:当线程被重新唤醒之后,没有判断标记,直接执行了下面的代码
*
*解决办法:将标记处的if改成while
*
*问题描述:继续运行程序,会出现死锁的情况(4个线程同时处于等待状态)
*原因:唤醒的是本方的线程,最后导致所有的线程都处于等待状态.
*
*解决办法:将notify改成notifyAll.保证将对方的线程唤醒
*
*死锁:出现的情况有两种
*1.所有的线程处于等待状态
*2.锁之间进行嵌套调用
*
*/
public class Demo5 { public static void main(String[] args) { //1.准备数据 Product1 product = new Product1(); //2.创建生产消费任务 Producer1 producer = new Producer1(product); Consumer1 consumer = new Consumer1(product); //3.创建生产消费线程 Thread thread0 = new Thread(producer); Thread thread1 = new Thread(producer); Thread thread2 = new Thread(consumer); Thread thread3 = new Thread(consumer); //4.开启线程 thread0.start(); thread1.start(); thread2.start(); thread3.start(); } } //数据类 class Product1{ String name; double price; int count; //标识 boolean flag; //准备生产 public synchronized void setProduce(String name,double price) { while (flag == true) { try { wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } this.name = name; this.price = price; System.out.println(Thread.currentThread().getName()+" 生产了:"+name+" 产品的数量:"+count+" 产品的价格:"+price); count++; flag = !flag; //唤醒消费线程 //notify(); notifyAll(); } //准备消费 public synchronized void consume() { while (flag == false) { try { wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } System.out.println(Thread.currentThread().getName()+" 消费了:"+name+" 产品的数量:"+count+" 产品的价格:"+price); flag = !flag; //唤醒生产线程 //notify(); notifyAll(); } } //生产任务 class Producer1 implements Runnable{ Product1 product; public Producer1(Product1 product) { super(); this.product = product; } public void run() { while (true) { product.setProduce("bingbing", 10); } } } //消费任务 class Consumer1 implements Runnable{ Product1 product; public Consumer1(Product1 product) { super(); this.product = product; } public void run() { while (true) { product.consume(); } } }