• 【进程同步】 JAVA 单生产者-单消费者


    问题描述

    有界缓冲
    一个生产者一次放入缓冲区一个产品,且无限次循环
    一个消费者一次拿出缓冲区一个产品,且无限次循环
    两个进程独立

    问题条件;

    缓冲池满,则生产者不能放
    缓冲池空,则消费者不能取
    只能一个生产者/消费者对缓冲区进行操作

    分析

    (1)进程个数:生产者P1 消费者P2
    (2)关系分析:互斥:P1 P2互斥访问 同步:P1生产之后P2才能消费
    (3)整理思路:PV解决同步、异步
    (4)信号量设置:
    ①互斥信号量(mutex):初值为1,控制进程互斥访问缓冲池
    ②同步信号量(full):初值为0,记录缓冲池中“满”的缓冲区的数量
    ③同步信号量(empty):初值为n,记录缓冲池中“空”的缓冲区的数量

    注意项

    进程进入临界区前要先检查,若无其他进程访问,则进入临界区并设置访问标志
    互斥信号量的PV操作要紧邻临界区。

    JAVA实现

    要求

    生产者和消费者是否想要进入缓冲区是随机的。

    代码

    package os.First;
    import java.util.Random;
    /*-----------------------消费者生产者随机访问-----------------------------------*/
    public class No1 {
    	public static void main(String[] args){
    		while(true) {
    			Random random=new Random();
    			int flag=random.nextInt(2);
    			if(flag==1) {
    				Producer p=new Producer();
    				Thread p1=new Thread(p);
    				p1.start();
    			}
    			else {
    				Consumer q=new Consumer();
    				Thread q1=new Thread(q);
    				q1.start();
    			}
    		}
    	}
    		
    }
    
    	//--------------------PV操作-------------------------
    	class PV{
    		int number=0;//初始化信号量
    		PV(){}
    		PV(int number){//设置信号量个数
    			this.number=number;
    		}
    		public synchronized void P() {//P操作
    			number--;
    			if(number<0) {
    				try {
    					this.wait();
    				}catch(InterruptedException e) {
    					e.printStackTrace();
    				}
    			}
    		}
    		
    		public synchronized void V(){//V操作
    			number++;
    			if(number<=0) {
    				this.notify();
    			}
    		}
    	}
    	//--------------------------一些初始化---------------------------
    	class Data{
    		static  PV empty=new PV(10);
    		static PV full=new PV(0);
    		static PV mutex=new PV(1);
    		public static int count=0;
    	}
    	
    	//-------------------------生产者------------------------------
    		/*生产一个产品 
    		P(empty)
    		P(mutex) 
    		产品放入缓冲区
    		V(mutex)
    		V(full) //增加一个产品 */
    		class Producer implements Runnable{
    			public void run() {
    				Data.empty.P();
    				Data.mutex.P();
    				System.out.println("生产者生产了产品,该产品被放入了缓冲区,缓冲区产品数量为"+(++Data.count));
    				Data.mutex.V();
    				Data.full.V();
    			}
    		}
    		 
    		//------------------------------消费者------------------------
    		/*
    		P(full)
    		P(mutex)
    		从缓冲区取出一个产品 
    		V(mutex) 
    		V(empty)
    		使用产品 
    		*/
    		class Consumer implements Runnable{
    			public void run() {
    				Data.full.P();
    				Data.mutex.P();			
    				System.out.println("消费者获得了一个产品,缓冲区产品数量为"+(--Data.count));
    				Data.mutex.V();
    				Data.empty.V();
    			}
    		}
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
  • 相关阅读:
    爬虫笔记15——爬取网页数据并使用redis数据库set类型去重存入,以爬取芒果踢V为例
    记我第一次做线下技术分享的那些事
    微服务的注册发现和微服务架构下的负载均衡
    C++ STL: list使用及源码剖析
    linux下docker容器安装已经docker基本使用命令详解
    列表和字典练习
    爬虫常用句法
    Apache Atlas 是什么?
    Salesforce action function调用不到的解决方式
    c++基础第二章:函数
  • 原文地址:https://blog.csdn.net/misakisaigao/article/details/127671020