生产者 消费者 (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
    评论
好的,下面是一个简单的使用wait()和notify()实现的生产者-消费者模型: ``` java public class ProducerConsumer { private List<Integer> buffer = new ArrayList<>(); private int maxSize = 5; public synchronized void produce() throws InterruptedException { while (buffer.size() == maxSize) { wait(); } int item = new Random().nextInt(); buffer.add(item); System.out.println("Produced: " + item); notify(); } public synchronized void consume() throws InterruptedException { while (buffer.size() == 0) { wait(); } int item = buffer.remove(0); System.out.println("Consumed: " + item); notify(); } } ``` 在上述代码中,`buffer`是一个用来存储生产者生产的数据的缓冲区,`maxSize`是缓冲区的最大大小,`produce()`和`consume()`分别表示生产者消费者的行为。在`produce()`和`consume()`方法中,使用了`wait()`和`notify()`方法来实现线程的等待和唤醒。 在生产者线程中,如果缓冲区已满,就让线程等待(调用`wait()`方法)。如果缓冲区不满,就生产一个随机数,并且将其加入缓冲区中,然后唤醒等待的消费者线程(调用`notify()`方法)。 在消费者线程中,如果缓冲区为空,就让线程等待(调用`wait()`方法)。如果缓冲区不为空,就从缓冲区中取出一个数据,并且将其打印出来,然后唤醒等待的生产者线程(调用`notify()`方法)。 注意,以上代码仅作为示例,是一个比较简单的实现。在实际生产环境中,可能需要更加完善的实现方式来保证线程安全和性能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值