Java实现生产者消费者模型

1,719 阅读3分钟

Java实现生产者消费者模型

信号量方式

import java.util.ArrayDeque;
import java.util.concurrent.Semaphore;

/**
 * Java 信号量实现生产者消费者模型
 */
public class ProducerAndCustomer {
	public static void main(String[] args) {
		Manager manager = new Manager();
		for (int i = 0; i < 3; i++) {
			Thread producer = new Thread(() -> {
				while (true) {
					manager.put(new Object());
					try {
						Thread.sleep(10);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			});
			producer.setName("生产者线程" + i);
			producer.start();
			Thread customer = new Thread(() -> {
				while (true) {
					manager.take();
					// 让生产速度大于消费速度
					try {
						Thread.sleep(100);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			});
			customer.setName("消费者线程" + i);
			customer.start();
		}
	}

	static class Manager {
		// 互斥信号量,实现对缓存区的互斥访问
		Semaphore mutex = new Semaphore(1);
		// 同步信号量,表示空缓冲区数量
		Semaphore empty = new Semaphore(10);
		// 同步信号量,表示产品的数量,即非空缓冲区的数量
		Semaphore full = new Semaphore(0);
		// 存储载体
		ArrayDeque<Object> items = new ArrayDeque<>();

		// 当前生产数量
		static int putNum = 0;
		// 当前消费数量
		static int getNum = 0;

		// 生产
		public void put(Object item) {
			try {
				// 确保当前还有空间剩余,empty进行减一
				empty.acquire();
				// 互斥访问临界区
				mutex.acquire();
				// 增加库存
				items.addLast(item);
				putNum++;
				System.out.println(Thread.currentThread().getName() + "正在生产第" + putNum + "个产品");
				// 非空信号量加一
				full.release();
			} catch (InterruptedException e) {
				e.printStackTrace();
			} finally {
				mutex.release();
			}
		}

		// 消费
		public Object take() {
			try {
				// 确保当前有产品可拿,full进行减一
				full.acquire();
				// 互斥访问临界区
				mutex.acquire();
				// 减少库存
				Object item = items.removeFirst();
				getNum++;
				System.out.println(Thread.currentThread().getName() + "正在消费第" + getNum + "个产品");
				// 空信号量加一
				empty.release();
				return item;
			} catch (InterruptedException e) {
				e.printStackTrace();
			} finally {
				// 退出临界区
				mutex.release();
			}
			return null;
		}
	}
}

synchronized方式

/**
 * synchronized 实现生产者消费者模型
 *
 * @author zsw
 * @date 2020/08/04 18:42
 */
public class Demo1 {
	static Object lock = new Object();
	// 缓冲区剩余数量
	static int empty = 10;
	// 缓冲区已有数量
	static int full = 0;
	// 当前生产的是第几个产品
	static int putNum = 0;
	// 当前消费的是第几个产品
	static int getNum = 0;

	public static void main(String[] args) {
		for (int i = 0; i < 3; i++) {
			Thread producer = new Thread(new Producer(lock));
			producer.setName("生产者线程" + i);
			producer.start();

			Thread customer = new Thread(new Customer(lock));
			customer.setName("消费者线程" + i);
			customer.start();
		}
	}

	static class Producer implements Runnable {
		final Object lock;

		public Producer(Object lock) {
			this.lock = lock;
		}

		@Override
		public void run() {
			while (true) {
				synchronized (lock) {
					try {
						while (empty <= 0) {
							lock.wait();
						}
						putNum++;
						empty--;
						full++;
						System.out.println(Thread.currentThread().getName() + "正在生产第" + putNum + "个产品");
					} catch (InterruptedException e) {
						e.printStackTrace();
					} finally {
						lock.notifyAll();
						try {
							Thread.sleep(10);
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					}
				}
			}

		}
	}

	static class Customer implements Runnable {
		final Object lock;

		public Customer(Object lock) {
			this.lock = lock;
		}

		@Override
		public void run() {
			while (true) {
				synchronized (lock) {
					try {
						while (full <= 0) {
							lock.wait();
						}
						getNum++;
						full--;
						empty++;
						System.out.println(Thread.currentThread().getName() + "正在消费第" + getNum + "个产品");
					} catch (InterruptedException e) {
						e.printStackTrace();
					} finally {
						lock.notifyAll();
						try {
							Thread.sleep(100);
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					}
				}
			}
		}
	}
}

Lock方式

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * lock实现生产者消费者模型
 *
 * @author zsw
 * @date 2020/08/04 19:01
 */
public class Demo2 {
	// 缓冲区剩余数量
	static int empty = 10;
	// 缓冲区已有数量
	static int full = 0;
	// 当前生产的是第几个产品
	static int putNum = 0;
	// 当前消费的是第几个产品
	static int getNum = 0;
	static ReentrantLock lock = new ReentrantLock();
	static Condition condition = lock.newCondition();

	public static void main(String[] args) {
		for (int i = 0; i < 3; i++) {
			Thread producer = new Thread(new Producer());
			producer.setName("生产者线程" + i);
			producer.start();

			Thread customer = new Thread(new Customer());
			customer.setName("消费者线程" + i);
			customer.start();
		}
	}

	static class Producer implements Runnable {
		@Override
		public void run() {
			while (true) {
				try {
					lock.lock();
					while (empty <= 0) {
						condition.await();
					}
					full++;
					empty--;
					putNum++;
					System.out.println(Thread.currentThread().getName() + "正在生产第" + putNum + "个产品");
					condition.signalAll();
				} catch (InterruptedException e) {
					e.printStackTrace();
				} finally {
					lock.unlock();
					try {
						Thread.sleep(10);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		}
	}

	static class Customer implements Runnable {
		@Override
		public void run() {
			while (true) {
				try {
					lock.lock();
					while (full <= 0) {
						condition.await();
					}
					full--;
					empty++;
					getNum++;
					System.out.println(Thread.currentThread().getName() + "正在消费第" + getNum + "个产品");
					condition.signalAll();
				} catch (InterruptedException e) {
					e.printStackTrace();
				} finally {
					lock.unlock();
					try {
						Thread.sleep(100);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		}
	}

}