Java multi-threading - the use of wait / notify implement producer / consumer model

Disclaimer: This article is a blogger original article, shall not be reproduced without the bloggers allowed. https://blog.csdn.net/kingslave1/article/details/78395697

Scene Description:

Producer / consumer model is a learning process and thread rather classic question, in this scene as follows:

There is a warehouse (Repository), there are several producers (Producer) and several consumers (Consumer), the producer can produce products (Procuct) and stored (push) warehouse, consumers can remove (pop) from the warehouse and consumer products.

I hope to use synchronize locking mechanism and wait () / notifyAll () or notify () method implementation, the following code. But the actual test found that when using the notify method, the thread notifies threads only recently used, over time it will become the only two threads are actually running. The use notifyAll () method, the maximum number of warehouses actual product is only created the largest number of producers, but can not reach the maximum number of own pre-defined yet figured here. Visual estimation is the position of my thread method calls or calls wake problem with the way, working to resolve.



Implementation code:

import java.util.ArrayList;

/**
 * 多生产者多消费者单仓库的生产者消费者模式
 * @author breezefaith
 *
 */
class Product{
	private int productId;

	public Product(int productId) {
		super();
		this.productId = productId;
	}

	@Override
	public String toString() {
		return "Product["+productId+"]";
	}

}

class Repository{
	private int maxSize;
	private ArrayList<Product> list;

	public Repository(int maxSize) {
		super();
		this.maxSize = maxSize;
		list=new ArrayList<>(maxSize);
	}
	public void setMaxSize(int maxSize) {
		if(maxSize<=list.size()) {
			System.err.println("New size is smaller than the original.");
			return;
		}
		ArrayList<Product> newList=new ArrayList<>(maxSize);
		newList.addAll(list);
		list=newList;
	}
	public int getMaxSize() {
		return maxSize;
	}
	public int getCurrentSize() {
		return list.size();
	}
	public void push(Product product) {
		list.add(product);
	}
	public Product pop() {
		return list.remove(0);
	}
}

class Producer extends Thread{
	private Repository repository;
	private static int productId;
	public Producer(Repository repository) {
		super();
		this.repository = repository;
	}

	public Product produce() {
		Product product=new Product(productId++);
		System.out.println("生产者 "+Thread.currentThread().getName()+" 生产了产品 "+product+",剩余:"+(repository.getCurrentSize()+1));
		return product;
	}

	@Override
	public void run() {
		synchronized (repository) {
			try {
				while(true) {
					Thread.sleep(1000);
					if(repository.getCurrentSize()<repository.getMaxSize()) {
						repository.push(produce());
					}else {
						System.err.println("Producer "+Thread.currentThread().getName()+" want to produce a product, but repository is full.");
					}
					repository.notifyAll();
					repository.wait();
				}
			}catch(InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

}

class Consumer extends Thread{
	private Repository repository;

	public Consumer(Repository repository) {
		super();
		this.repository = repository;
	}

	public Product consume() {
		Product product=repository.pop();
		System.out.println("消费者 "+Thread.currentThread().getName()+" 消费了产品 "+product+",剩余:"+repository.getCurrentSize());
		return product;
	}

	@Override
	public void run() {
		synchronized (repository) {
			try {
				while(true) {
					Thread.sleep(1000);
					if(repository.getCurrentSize()>0) {
						consume();
					}else {
						System.err.println("Consumer "+Thread.currentThread().getName()+" consume a product, but repository is empty.");
					}
					repository.notifyAll();
					repository.wait();
				}
			}catch(InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}

public class Run {

	public static void main(String[] args) {
		Repository repository=new Repository(3);
		Producer p1=new Producer(repository),
				p2=new Producer(repository),
				p3=new Producer(repository);
		p1.setName("p1");
		p2.setName("p2");
		p3.setName("p3");
		
		Consumer c1=new Consumer(repository),
				c2=new Consumer(repository);
		c1.setName("c1");
		c2.setName("c2");
		
		p1.start();
		p2.start();
		p3.start();
		c1.start();
		c2.start();
	}

}


Test Results:

Producers p1 produced goods Product [0], remaining: 1
consumer c1 consumer product Product [0], remaining: 0
Consumer Product A c2 Consume, But Repository IS empty.
Producers p3 produced goods Product [1], remaining: 1
producer p2 produced goods product [2], remaining: 2
producer p3 produced goods product [3], remaining: 3
consumer c2 consumer product product [1], remaining: 2
consumers consume c1 product product [2], remaining: 1
producer p1 produced goods product [4], remaining: 2
consumer c1 consumer product product [3], remaining: 1
consumer c2 consumer product product [4], remaining: 0
producers p3 produced goods product [5], remaining: 1
producer p2 produced goods product [6], remaining: 2
producer p3 produced goods product [7], remaining: 3
consumer product c2 consumer products [5] remaining: 2
consumer c1 consumer product product [6], remaining: 1
producer p1 produced goods product [8], remaining: 2





Guess you like

Origin blog.csdn.net/kingslave1/article/details/78395697