生产者 消费者 (wait notify)

1、简介:

生产者-消费者(producer-consumer)问题是一个著名的线程同步问题。它描述的是:有一群生产者线程在生产产品,并将这些产品提供给消费者线程去消费。为使生产者与消费者之间能够并发执行,在两者之间设置了一个具有n个缓冲区的缓冲池,生产者将它所生产的产品放入一个缓冲区中;消费者可以从一个缓冲区中取走产品产生消费。尽管所有的生产者线程和消费者线程都是以异步方式运行的,但他们之间必须保持同步,即不允许消费者到一个空缓冲区去消费,也不允许生产者向一个已经被占用的缓冲区投放产品。【转】

2、 wait()、notify(),notifyAll()的使用

obj.wait()方法将使本线程挂起,并释放obj对象的monitor。只有其他线程调用obj对象的notify()或notifyAll()时,才可以被唤醒。
obj.notifyAll()方法唤醒所有该obj对象相关的沉睡线程,然后被唤醒的众多线程开始竞争obj对象的monitor占有权,最终得到的那个线程会继续执行下去,但其他线程还将继续等待。
obj.notify()方法是随机唤醒一个沉睡线程。
wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,
如:
synchronized(x){
x.notify()
//或者wait()
}
以上内容说明了为什么调用wait(),notify(),notifyAll()的线程必须要拥有obj实例对象的monitor占有权。
wait(),notify(),notifyAll() 方法必须在synchronized 方法内调用

每个对象实例都有一个等待线程队列。这些线程都是等待对该对象的同步方法的调用许可。对一个线程来说,有两种方法可以进入这个等待线程队列。一个是当其他线程执行同步方法时,自身同时也要执行该同步方法;另一个是调用obj.wait()方法。
当同步方法执行完毕或者执行wait()时,其他某个线程将获得对象的访问权。当一个线程被放入等待队列时,必须要确保可以通过notify()的调用来解冻该线程,以使其能够继续执行下去。

3 例子:

public class Queue {
	List<String> list=new LinkedList<String>();
	public synchronized String getRequest(){
		if (list.size()==0) {
			
			try {
				this.wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return list.remove(0);
		
	}
	public synchronized void putRequest(String msg){
		list.add(msg);
		this.notifyAll();
		
	}
}

生产者:
import java.util.Random;

public class Producer extends Thread {
	private Queue queue;
	private String clientName;

	public Producer(Queue queue, String clientName) {
		super(clientName);
		this.queue = queue;
		this.clientName = clientName;
	}

	@Override
	public void run() {
		// TODO Auto-generated method stub
		super.run();
		System.out.println("开始生产");
		for (int i = 0; i < 10; i++) {
			queue.putRequest(new Random().nextInt(1000)+" ");
		}
		System.out.println("生产结束");
	}
}

消费者:
public class Consumer extends Thread {
	private boolean stop = false;
	private Queue queue;

	public Consumer(boolean stop, Queue queue) {
		super();
		this.stop = stop;
		this.queue = queue;
	}

	public void shutdown() {
		stop = true;
		this.interrupt();
		try {
			this.join();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Override
	public void run() {
		// TODO Auto-generated method stub
		super.run();
		System.out.println("开始消费");
		while (!stop) {
			System.out.println("..");
			System.out.println("Consumer"+queue.getRequest());
		}
		System.out.println("[消费结束] shutdown.");
	}
}

Mian:
public static void main(String[] args) {
		// TODO Auto-generated method stub
		Queue queue=new Queue();
		Consumer consumer=new Consumer(false, queue);
		consumer.start();
		
		for (int i = 0; i < 1; i++) {
			Producer rroducer=new Producer(queue, " >>"+i);
			rroducer.start();
		}

	}




参考:


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值