首先用一个普通的stack来实现消费者和生产者。java
package concurrent; import java.util.Stack; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class StackPC { class MyStack{ private Stack stack = new Stack(); private int size = 0; public synchronized void push(int i ){ stack.push(i); size = size +1; } public synchronized int pop(){ int i = (int) stack.pop(); size = size -1; return i; } public boolean isEmpty(){ return stack.isEmpty(); } public int size(){ return size; } } class Producer{ private MyStack mystack ; public Producer(MyStack mystack){ this.mystack = mystack; } public void producer(){ try { synchronized (mystack){ if(mystack.size()>10) mystack.wait(); int i = (int) Math.round((Math.random()*100)); mystack.push(i); System.out.println("生产了"+i+"此时size为"+mystack.size()); mystack.notify(); } } catch (InterruptedException e) { e.printStackTrace(); } } } class Customer{ private MyStack mystack ; public Customer(MyStack mystack){ this.mystack = mystack; } public void customer(){ try { synchronized(mystack){ if(mystack.isEmpty()) mystack.wait(); int i = mystack.pop(); System.out.println("消费了"+i+"此时size为"+mystack.size); mystack.notify(); } } catch (InterruptedException e) { e.printStackTrace(); } } } public static void main(String[] args) { StackPC test = new StackPC(); StackPC.MyStack stack = test.new MyStack(); final StackPC.Producer p = test.new Producer(stack); final StackPC.Customer c = test.new Customer(stack); Runnable pRunner = new Runnable() { @Override public void run() { while(true){ p.producer(); } } }; Runnable cRunner = new Runnable() { @Override public void run() { while(true){ c.customer(); } } }; ExecutorService exe = Executors.newCachedThreadPool(); exe.execute(pRunner); exe.execute(cRunner); } }
运行结果以下:缓存
生产者最多生产到size为11的时候就会唤醒消费者进行消费,消费者消费到size为0时会唤醒生产者进行生产。当stack的容量大于0小于11时,生产和消费是并行运行的。这里因为cpu执行较快没有明显的生产消费交替进行,而是一次消费或者生产多个而后才交替执行。dom
上面是咱们本身使用stack来对产品进行缓存,其实java中已经有很是完善的类提供给咱们使用,使用阻塞队列来模拟生产者消费者问题实现更为简单。ide
package concurrent; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class BlockingQueueTest { public static void main(String[] args) throws InterruptedException { final BlockingQueue bq = new ArrayBlockingQueue(10); Runnable producer = new Runnable() { @Override public void run() { int i = 0; while(true){ try { i++; bq.put(i); System.out.println("生产了一个"+ i); Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); break; } } } }; Runnable customer = new Runnable() { @Override public void run() { while(true){ try { System.out.println("消费了一个"+bq.take()); Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); break; } } } }; ExecutorService exe = Executors.newCachedThreadPool(); exe.execute(producer); exe.execute(customer); // Thread.sleep(1000); // exe.shutdownNow(); } }
这里咱们不须要再手动写wait和notify,也不用对队列进行手动加锁,这里生产者生产的速度快与消费者,因此在开始的时候虽然是并行执行,可是生产者的速度较快,阻塞队列很快达到容量最大值10,这时候生产者没法继续生产,阻塞等待,当消费者消费后,容量减少,生产者继续生产。this
能够看出在容量到达10 之后,消费者消费一个生产者才继续生产一个,使用阻塞队列可有效平衡生产者和消费者。spa