Java入门到精通——基础篇之多线程实现简单的PV操作的进程同步
2015-03-22 17:28
666 查看
一、概述
PV操作是对信号量进行的操作。
进程同步是指在并发进程之间存在一种制约关系,一个进程的执行依赖另一个进程的消息,当一个进程没有得到另一个进程的消息时应等待,直到消息到达才被唤醒。举例:就像消费者与生产者的关系,说吃馒头把有一个碗能盛下6个馒头,厨师不停的生产馒头,顾客不停的吃馒头,此时厨师与顾客的关系就是同步。(如下图)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201504/86382651e3a1ee8a1b22648b124b8a55)
下面我就为大家利用java多线程的代码实现这个操作的过程。
二、代码展示。
1、ManTou.java
[java] view
plaincopy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/9e12f1d3e499fc949c886e7c9e0484f9)
package com.gaowei.PV;
public class ManTou {
int id;
ManTou(int id) {
this.id = id;
}
public String toString() {
return "ManTou : " + id;
}
}
2、厨师类Pclient.java
[java] view
plaincopy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/9e12f1d3e499fc949c886e7c9e0484f9)
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
[java] view
plaincopy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/9e12f1d3e499fc949c886e7c9e0484f9)
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
[java] view
plaincopy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/9e12f1d3e499fc949c886e7c9e0484f9)
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
[java] view
plaincopy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/9e12f1d3e499fc949c886e7c9e0484f9)
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、效果图
![](https://oscdn.geek-share.com/Uploads/Images/Content/201504/2c6300e40c1942509eb48cfca3705079)
由于顾客吃馒头慢要6s吃个馒头,而厨师做馒头快1s就能做一个馒头所以从图中的分布大家就可以发现厨师做到了第6个馒头了消费者才吃了1个馒头接下来由于碗中只能盛下6个馒头所以厨师只有等着顾客吃一个然后在放一个馒头到碗里,一直到最后厨师20个馒头做完了顾客还得继续把剩下的6个馒头吃完才能结束。
三、总结。
利用多线程实现了PV操作了接下了就要思考一下PV操作的好处在哪里?在实现代码的过程中说一个细节问题当顾客吃了一个馒头之后就会通知厨师这个线程来生产馒头,厨师生产一个馒头也会去通知顾客来吃馒头。这样的思路就和观察者思路差不多能解决生产者与消费者的耦合。说高大上点就是生产者干自己的事情,消费者干自己的事情,通过碗中消息来通知生产者该干嘛,消费者该干嘛。这样的话就把生产者和消费者的关系解耦了。
PV操作是对信号量进行的操作。
进程同步是指在并发进程之间存在一种制约关系,一个进程的执行依赖另一个进程的消息,当一个进程没有得到另一个进程的消息时应等待,直到消息到达才被唤醒。举例:就像消费者与生产者的关系,说吃馒头把有一个碗能盛下6个馒头,厨师不停的生产馒头,顾客不停的吃馒头,此时厨师与顾客的关系就是同步。(如下图)
下面我就为大家利用java多线程的代码实现这个操作的过程。
二、代码展示。
1、ManTou.java
[java] view
plaincopy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
package com.gaowei.PV;
public class ManTou {
int id;
ManTou(int id) {
this.id = id;
}
public String toString() {
return "ManTou : " + id;
}
}
2、厨师类Pclient.java
[java] view
plaincopy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
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
[java] view
plaincopy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
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
[java] view
plaincopy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
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
[java] view
plaincopy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
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操作的好处在哪里?在实现代码的过程中说一个细节问题当顾客吃了一个馒头之后就会通知厨师这个线程来生产馒头,厨师生产一个馒头也会去通知顾客来吃馒头。这样的思路就和观察者思路差不多能解决生产者与消费者的耦合。说高大上点就是生产者干自己的事情,消费者干自己的事情,通过碗中消息来通知生产者该干嘛,消费者该干嘛。这样的话就把生产者和消费者的关系解耦了。
相关文章推荐
- Java入门到精通——基础篇之多线程实现简单的PV操作的进程同步
- Java入门到精通——基础篇之多线程实现简单的PV操作的进程同步
- Java入门到精通——基础篇之多线程实现简单的PV操作的进程同步
- Java入门到精通——基础篇之多线程实现简单的PV操作的进程同步
- Java入门到精通——基础篇之多线程实现简单的PV操作的进程同步
- Java多线程的简单实现以及耗时操作的效率对比
- Java中使用synchronized关键字实现简单同步操作示例
- 进程的PV操作及互斥同步实现
- 用PV操作解决经典进程同步问题 C#实现
- 进程同步-生产者和消费者(PV操作实现——java多线程模拟)
- 关于网宿厦门研发中心笔试的一道PV操作题:利用java中的多线程实现生产者与消费者的同步问题
- C#使用互斥量(Mutex)实现多进程并发操作时多进程间线程同步操作(进程同步)的简单示例代码及使用方法
- 黑马程序员_Java基础:实现多线程对共有数据的同步操作
- 线程进程【重磅出击】 java入门到精通——多线程(上)
- ℃江让您从精通到入门:Android Studio 简单实现ViewPager,可做APP操作提示
- 用PV操作实现多线程间同步互斥(PV)
- [java]增删改查后给出操作提示后跳转到数据列表的小问题解决[简单实现]
- java实现简单的异或操作(用于文件简单加密)
- java简单多线程方式+实现文件上传(spring mvc + jquery.form.js 框架)
- 算法设计、分析与实现 从入门到精通 C、C++和Java 这本书的堆实现85页C++语言实现有问题