• 经典问题-生产者和消费者问题


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

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

    本程序只有一个生产者和一个消费者,使用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();
    			}
    		}
    	}
    }


  • 相关阅读:
    冲刺(9)
    冲刺(8)
    冲刺(7)
    C#的post请求 捕获错误代码的内容
    [转载]Memory Limits for 32-bit and 64-bit processes
    IIS 503
    识别chrome浏览器
    时间同步
    修改Visual Studio启动画面授权信息
    Temporary ASP.NET Files权限问题
  • 原文地址:https://www.cnblogs.com/wally/p/4477038.html
Copyright © 2020-2023  润新知