zoukankan      html  css  js  c++  java
  • 经典问题-生产者和消费者问题

    生产者和消费者是一个多线程同步的经典案例,该问题描述了两个共享固定大小缓冲区的线程,即所谓的“生产者”和“消费者”,顾名思义,生产者指的就是生产一定的数据量到缓冲区,而消费者就是从缓冲区取走一定的数据。

    生产者和消费者问题要解决一个死锁问题,就是当缓冲区已经满的时候,生产者占着它等待消费者来取走数据,而消费者则等着生产者让出缓冲区的权利好取走数据,于是就相互等待,从而造成死锁。

    本程序只有一个生产者和一个消费者,使用wait和notify(nitify)方法来避免死锁问题,这里得提一下wait和notify(notifyAll)方法,线程中的wait、notify以及notifyAll方法:都是定义在Object类中的final方法,即所有的类都默认拥有这3个方法,但只用于synchronized关键字作用的范围内,并且是搭配着一起使用;wait方法是通知当前线程等待并释放对象锁;notify方法是通知等待此对象锁的一个线程重新获得线程锁;notifyAll是唤醒所有等待此对象锁的线程。

    public class ProducerConsumer {
    	
    	public static void main(String[] args) {
    		
    		SyncStack myStack = new SyncStack(6);
    		
    		Producer producer = new Producer(myStack);
    		Consumer consumer = new Consumer(myStack);
    		
    		Thread t1 = new Thread(producer);
    		Thread t2 = new Thread(consumer);
    		
    		t1.start();
    		t2.start();
    		
    	}
    }
    
    class Bread {
    	
    	private int id;
    	
    	Bread(int id) {
    		this.id = id;
    	}
    	
    	public int getId() {
    		return id;
    	}
    }
    
    
    class SyncStack {
    	
    	private int size;
    	private int index = 0;
    	private Bread[] myBread;
    	
    	SyncStack(int size) {
    		this.size = size;
    		myBread = new Bread[size];
    	}
    	
    	public synchronized void put(Bread bread) {
    		while (index == size) {
    			try {
    				this.wait();
    			} catch (InterruptedException e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			}
    		}
    		myBread[index] = bread;
    		++index;
    		System.out.println("Producer puts bread: " + bread.getId());
    		this.notify();
    	}
    	
    	public synchronized Bread remove() {
    		while (index == 0) {
    			try {
    				this.wait();
    			} catch (InterruptedException e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			}
    		}
    		--index;
    		System.out.println("Consumer removers bread: " + myBread[index].getId());
    		this.notify();
    		return myBread[index];
    	}	
    	
    }
    
    class Producer extends Thread {
    	
    	private SyncStack myStack;
    	
    	Producer(SyncStack myStack) {
    		this.myStack = myStack;
    	}
    	
    	public void run() {
    		
    		for (int i = 1; i <= 20; ++i) {
    			myStack.put(new Bread(i));
    			try {
    				Thread.sleep(1000);
    			} catch (InterruptedException e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			}
    		}
    	}
    }
    
    
    class Consumer extends Thread {
    	
    	private SyncStack myStack;
    	
    	Consumer(SyncStack myStack) {
    		this.myStack = myStack;
    	}
    	
    	public void run() {	
    		for (int i = 1; i <= 20; ++i) {	
    			Bread bread = myStack.remove();
    			try {
    				Thread.sleep(2000);
    			} catch (InterruptedException e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			}
    		}
    	}
    }


  • 相关阅读:
    判断一本书是否值得买
    【Python】对我自己的博客进行统计,看看哪年哪月发帖量最大
    在python中使用正则表达式(转载)
    【English】What is a Java StringWriter, and when should I use it?(转帖)
    【Java】利用java.io.PrintWriter写出文本文件
    [MySql]当虚拟机的IP地址自动更换后,JDBC使用原来的配置连不上MySql数据库时所报的异常。
    java中的lastIndexOf( )函数是什么意思
    day63_SpringMVC学习笔记_01
    day62_Mybatis学习笔记_02
    day61_Mybatis学习笔记_01
  • 原文地址:https://www.cnblogs.com/wally/p/4477038.html
Copyright © 2011-2022 走看看