浅谈Java简单实现的生产者与消费者问题
一、面对生产者和消费者的问题,首先我们得明白几点:
生产者:生产数据;
消费者:消费数据。
消费者在没有数据可供消费的情况下,不能消费;
生产者在原数据没有被消费掉的情况下,不能生产新数据。
假设,数据空间只有一个。
实际上,如果实现了正确的生产和消费,则,两个线程应该是严格的交替执行。
synchronized关键字若用在代码中,形成一个同步块,且,必须要执行锁:
synchronized (锁对象) {
同步块
}
同步块使得锁对象称为thread monitor
二、代码实现:
1.首先我们建立一个生产者和消费者共同拥有的锁的类:
1 package com.mec.about_procuder_customer.core; 2 3 public class ProcuderCustomer { 4 //初始状态的数据为0个 5 protected static volatile int count = 0; 6 //执行锁 7 protected final static Object lock = new Object(); 8 }
上述代码有一个关键字volatile,它是保证线程之间有序的一种方式,最重要也是最直接的是禁止寄存器优化。就是如果线程run方法中只是一个循环,并没有执行语句,那么,这个线程将不会执行。
2.我们再来建立一个生产者的类:
1 package com.mec.about_procuder_customer.core; 2 3 //生产者 4 public class Procuder extends ProcuderCustomer implements Runnable { 5 6 //存放数据的空间 7 private int[] dataSpace; 8 9 public Procuder(int[] dataSpace, String threadName) { 10 this.dataSpace = dataSpace; 11 //启动线程 12 new Thread(this, threadName).start(); 13 } 14 15 @Override 16 public void run() { 17 int i = 0; 18 19 while (true) { 20 synchronized (lock) { 21 //判断是否空间已满 22 if (count < dataSpace.length) { 23 //产生者放数据 24 dataSpace[count] = i++; 25 System.out.println("[" + Thread.currentThread().getName() 26 + "]线程生产了一个数:" + dataSpace[count++] 27 + " " + count); 28 try { 29 //只是为了看的清楚,沉睡2秒 30 Thread.sleep(200); 31 } catch (InterruptedException e) { 32 e.printStackTrace(); 33 } 34 //唤醒消费者 35 lock.notify(); 36 } else { 37 try { 38 //使自己处于阻塞状态 39 lock.wait(); 40 } catch (InterruptedException e) { 41 e.printStackTrace(); 42 } 43 } 44 } 45 } 46 } 47 }
3.建立消费者的类:
1 package com.mec.about_procuder_customer.core; 2 3 //消费者 4 public class Customer extends ProcuderCustomer implements Runnable { 5 //存放数据的空间 6 private int[] dataSpace; 7 8 public Customer(int[] dataSpace, String threadName) { 9 this.dataSpace = dataSpace; 10 //启动线程 11 new Thread(this, threadName).start(); 12 } 13 14 @Override 15 public void run() { 16 while (true) { 17 //加锁 18 synchronized (lock) { 19 //判断是否有数据 20 if (count > 0) { 21 System.out.println("[" + Thread.currentThread().getName() 22 + "]线程消费了一个数:" + dataSpace[--count]); 23 //唤醒生产者 24 lock.notifyAll(); 25 } else { 26 try { 27 //使自己处于阻塞状态 28 lock.wait(); 29 } catch (InterruptedException e) { 30 e.printStackTrace(); 31 } 32 } 33 } 34 } 35 } 36 37 }
4.测试类:
1 package com.mec.about_procuder_customer.test; 2 3 import com.mec.about_procuder_customer.core.Customer; 4 import com.mec.about_procuder_customer.core.Procuder; 5 6 public class Test { 7 8 public static void main(String[] args) { 9 int[] data = new int[10]; 10 new Procuder(data, "生产者1"); 11 new Procuder(data, "生产者2"); 12 new Customer(data, "消费者"); 13 } 14 15 }
运行结果: