Java入门到精通——基础篇之多线程实现简单的PV操作的进程同步

一、概述
    PV操作是对信号量进行的操作。

    进程同步是指在并发进程之间存在一种制约关系,一个进程的执行依赖另一个进程的消息,当一个进程没有得到另一个进程的消息时应等待,直到消息到达才被唤醒。举例:就像消费者与生产者的关系,说吃馒头把有一个碗能盛下6个馒头,厨师不停的生产馒头,顾客不停的吃馒头,此时厨师与顾客的关系就是同步。(如下图)

    

    下面我就为大家利用java多线程的代码实现这个操作的过程。

二、代码展示。

1、ManTou.java

	package com.gaowei.PV;
	
	public class ManTou {
	
		int id; 
		ManTou(int id) {
			this.id = id;
		}
		public String toString() {
			return "ManTou : " + id;
		}
	}


2、厨师类Pclient.java

	package com.gaowei.PV;
	
	public class PClient implements Runnable {
	
		private SyncStack ss=null;
		public PClient(SyncStack ss){
			this.ss=ss;
		}
		@Override
		public void run() {
			for (int i = 0; i < 20; i++) {
				ManTou mt=new ManTou(i);
				ss.push(mt);
				System.out.println("生产了:"+mt);
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
	
		}
	
	}


3、顾客类Vclient.java

	package com.gaowei.PV;
	
	public class VClient implements Runnable {
		private SyncStack ss=null;
		public VClient(SyncStack ss){
			this.ss=ss;
		}
		@Override
		public void run() {
			for(int i=0; i<20; i++) {
				ManTou mt = ss.pop();
				System.out.println("消费了: " + mt);
				try {
					Thread.sleep(6000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}		
			}
		}
	
	}


4、碗类SyncStack.java

	package com.gaowei.PV;
	
	public class SyncStack {
			private int index=0;
			ManTou[] arrMT=new ManTou[6];
			
			//添加馒头
			public synchronized void push(ManTou mt){
				while (index==arrMT.length) {
				try {
					this.wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
					
				}
				this.notifyAll();
				arrMT[index]=mt;
				index++;
			}
			
			
			//吃馒头
			public synchronized  ManTou pop(){
				while(index==0){
					try {
						this.wait();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
				this.notifyAll();
				index--;
				return arrMT[index];
			}
	}


5、客户端显示效果代码PVClient.java

	package com.gaowei.PV;
	
	public class PVClient {
	
		public static void main(String[] args) {
			
			SyncStack ss = new SyncStack();
			PClient p = new PClient(ss);
			VClient v= new VClient(ss);
		
			new Thread(p).start();
			new Thread(v).start();
		}
	
	}


6、效果图


    由于顾客吃馒头慢要6s吃个馒头,而厨师做馒头快1s就能做一个馒头所以从图中的分布大家就可以发现厨师做到了第6个馒头了消费者才吃了1个馒头接下来由于碗中只能盛下6个馒头所以厨师只有等着顾客吃一个然后在放一个馒头到碗里,一直到最后厨师20个馒头做完了顾客还得继续把剩下的6个馒头吃完才能结束。

三、总结。

    利用多线程实现了PV操作了接下了就要思考一下PV操作的好处在哪里?在实现代码的过程中说一个细节问题当顾客吃了一个馒头之后就会通知厨师这个线程来生产馒头,厨师生产一个馒头也会去通知顾客来吃馒头。这样的思路就和观察者思路差不多能解决生产者与消费者的耦合。说高大上点就是生产者干自己的事情,消费者干自己的事情,通过碗中消息来通知生产者该干嘛,消费者该干嘛。这样的话就把生产者和消费者的关系解耦了。

posted @ 2015-03-21 15:17  夏至冬末  阅读(580)  评论(0编辑  收藏  举报