并发实践-生产者消费者问题
Java中实现生产者消费者通常有以下几种方式:
- 用object原生的wait() 和 notify()做同步,并用synchronized对存储加锁
- 用condition的await() 和signal()做同步。并用concurrent.locks.Lock,
- 直接使用concurrent.BlockingQueue。
- 使用PipedInputStream/PipedOutputStream。
- 使用信号量semaphore。
解决问题的核心
保证同一资源被多个线程并发访问时的完整性。常用的同步方法是采用信号或加锁机制,保证资源在任意时刻至多被一个线程访问。
public class ProducerAndConsumer { private final int MAX_LEN = 10; private Queue<Integer> queue = new LinkedList<Integer>(); class Producer extends Thread { @Override public void run() { producer(); } private void producer() { while(true) { synchronized (queue) { while (queue.size() == MAX_LEN) { queue.notify(); System.out.println("当前队列满"); try { queue.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } queue.add(1); queue.notify(); System.out.println("生产者生产一条任务,当前队列长度为" + queue.size()); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } } } } class Consumer extends Thread { @Override public void run() { consumer(); } private void consumer() { while (true) { synchronized (queue) { while (queue.size() == 0) { queue.notify(); System.out.println("当前队列为空"); try { queue.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } queue.poll(); queue.notify(); System.out.println("消费者消费一条任务,当前队列长度为" + queue.size()); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } } } } public static void main(String[] args) { ProducerAndConsumer pc = new ProducerAndConsumer(); Producer producer = pc.new Producer(); Consumer consumer = pc.new Consumer(); producer.start(); consumer.start(); } }
public class ProducerAndConsumer1 { private final int MAX_LEN = 10; private Queue<Integer> queue = new LinkedList<Integer>(); private final Lock lock = new ReentrantLock(); private final Condition condition = lock.newCondition(); class Producer extends Thread { @Override public void run() { producer(); } private void producer() { while(true) { lock.lock(); try { while (queue.size() == MAX_LEN) { System.out.println("当前队列满"); try { condition.await(); } catch (InterruptedException e) { e.printStackTrace(); } } queue.add(1); condition.signal(); System.out.println("生产者生产一条任务,当前队列长度为" + queue.size()); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } finally { lock.unlock(); } } } } class Consumer extends Thread { @Override public void run() { consumer(); } private void consumer() { while (true) { lock.lock(); try { while (queue.size() == 0) { System.out.println("当前队列为空"); try { condition.await(); } catch (InterruptedException e) { e.printStackTrace(); } } queue.poll(); condition.signal(); System.out.println("消费者消费一条任务,当前队列长度为" + queue.size()); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } finally { lock.unlock(); } } } } public static void main(String[] args) { ProducerAndConsumer pc = new ProducerAndConsumer(); Producer producer = pc.new Producer(); Consumer consumer = pc.new Consumer(); producer.start(); consumer.start(); } }
public class ProducerAndConsumer { private BlockingQueue<Integer> queue = new LinkedBlockingQueue<Integer>(10); class Producer extends Thread { @Override public void run() { producer(); } private void producer() { while(true) { try { queue.put(1); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("生产者生产一条任务,当前队列长度为" + queue.size()); try { Thread.sleep(new Random().nextInt(1000)+500); } catch (InterruptedException e) { e.printStackTrace(); } } } } class Consumer extends Thread { @Override public void run() { consumer(); } private void consumer() { while (true) { try { queue.take(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("消费者消费一条任务,当前队列长度为" + queue.size()); try { Thread.sleep(new Random().nextInt(1000)+500); } catch (InterruptedException e) { e.printStackTrace(); } } } } public static void main(String[] args) { ProducerAndConsumer pc = new ProducerAndConsumer(); Producer producer = pc.new Producer(); Consumer consumer = pc.new Consumer(); producer.start(); consumer.start(); } }
class Stock { List<String> stock = new LinkedList(); // 互斥量,控制共享数据的互斥访问 private Semaphore mutex = new Semaphore(1); // canProduceCount可以生产的总数量。 通过生产者调用acquire,减少permit数目 private Semaphore canProduceCount = new Semaphore(10); // canConsumerCount可以消费的数量。通过生产者调用release,增加permit数目 private Semaphore canConsumerCount = new Semaphore(0); public void put(String computer) { try { // 可生产数量 -1 canProduceCount.acquire(); mutex.acquire(); // 生产一台电脑 stock.add(computer); System.out.println(computer + " 正在生产数据" + " -- 库存剩余:" + stock.size()); } catch (InterruptedException e) { e.printStackTrace(); } finally { // 释放互斥锁 mutex.release(); // 释放canConsumerCount,增加可以消费的数量 canConsumerCount.release(); } // 无逻辑作用,放慢速度 try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } public void get(String consumerName) { try { // 可消费数量 -1 canConsumerCount.acquire(); mutex.acquire(); // 从库存消费一台电脑 String removedVal = stock.remove(0); System.out.println(consumerName + " 正在消费数据:" + removedVal + " -- 库存剩余:" + stock.size()); } catch (InterruptedException e) { e.printStackTrace(); } finally { mutex.release(); // 消费后释放canProduceCount,增加可以生产的数量 canProduceCount.release(); } } } public class SemaphoreTest { public static void main(String[] args) { // 用于多线程操作的库存变量 final Stock stock = new Stock(); // 定义两个生产者和两个消费者 Thread dellProducer = new Thread(new Runnable() { @Override public void run() { while (true) { stock.put("Del"); } } }); Thread macProducer = new Thread(new Runnable() { @Override public void run() { while (true) { stock.put("Mac"); } } }); Thread consumer1 = new Thread(new Runnable() { @Override public void run() { while (true) { stock.get("zhangsan"); } } }); Thread consumer2 = new Thread(new Runnable() { @Override public void run() { while (true) { stock.get("李四"); } } }); dellProducer.start(); macProducer.start(); consumer1.start(); consumer2.start(); } }
浙公网安备 33010602011771号