新型生产者消费者解决方案

215 阅读3分钟

问题描述

实现生产者消费者算法,多个线程同时生产数据,多个线程同时消费数据,要求容量空间有上限,消费者和生产者需要相互等待。

解题思路

传统思路: 利用java的wait和notify实现,如果使用数组,则每次放和取都加锁,并判断是否满了或者是否队列已空。 满了则唤醒消费线程,生产线程等待; 空了则唤醒生产线程,消费线程等待。

本文思路: 使用数组作为容器,每次生产或者消费前获取索引位置,根据数组当前位置的状态判断是否生产或者是否消费。

代码实现

import java.util.Arrays;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;

/**
 * @Function
 * 
 *
 * @Update
 *
 * @Author cc
 * @CreateTime 2020年03月05日
 */
public class Day2020005 {

	public static void main(String[] args) throws Exception {
		Day2020005 main = new Day2020005();
		main.run();
	}

	long[] array = new long[100];
	{
		Arrays.fill(array, -1);
	}
	AtomicLong produceIndex = new AtomicLong();
	AtomicLong consumeIndex = new AtomicLong();
	
	long lastProduceCount = 0;
	long lastConsumeCount = 0;

	void run() throws Exception {
		for (int i=0; i<10; i++) {
			new Thread(new ProducerThread()).start();
			new Thread(new ConsumerThread()).start();
		}
		
		
		
		Executors.newScheduledThreadPool(1).scheduleAtFixedRate(() -> {
			long curProduceCount = produceIndex.longValue();
			long curConsumeCount = consumeIndex.longValue();
			
			StringBuilder sb = new StringBuilder();
			sb.append("produce_index ").append(produceIndex.longValue());
			sb.append(", consume_index ").append(consumeIndex.longValue());
			sb.append(", produce_speed ").append(curProduceCount - lastProduceCount);
			sb.append(", consume_speed ").append(curConsumeCount - lastConsumeCount);
			
			System.out.println(sb);
			
			lastProduceCount = curProduceCount;
			lastConsumeCount = curConsumeCount;
		}, 0, 1, TimeUnit.SECONDS);
	}

	class ProducerThread implements Runnable {

		public void run() {
			while (true) {
				long index = produceIndex.incrementAndGet();
				while (index > consumeIndex.longValue() + array.length || array[(int) (index % array.length)] != -1) {
//					LockSupport.parkNanos(1);
				}
				array[(int) (index % array.length)] = index;
//				System.out.println("produce " + index);
			}
		}
	}
	
	class ConsumerThread implements Runnable {

		public void run() {
			while (true) {
				long index = consumeIndex.incrementAndGet();
				while (index > produceIndex.longValue() || array[(int) (index % array.length)] == -1) {
//					LockSupport.parkNanos(1);
				}
//				System.out.println("consume " + array[(int) (index % array.length)]);
				array[(int) (index % array.length)] = -1;
			}
		}
	}
}

执行结果: 如果加上LockSupport.parkNanos(1)

produce_index 5604, consume_index 5509, produce_speed 5604, consume_speed 5509
produce_index 64924, consume_index 64864, produce_speed 59320, consume_speed 59355
produce_index 133237, consume_index 133136, produce_speed 68313, consume_speed 68272
produce_index 199752, consume_index 199650, produce_speed 66515, consume_speed 66514
produce_index 260743, consume_index 260650, produce_speed 60991, consume_speed 61000
produce_index 314954, consume_index 314854, produce_speed 54211, consume_speed 54204
produce_index 369850, consume_index 369749, produce_speed 54896, consume_speed 54895
produce_index 431427, consume_index 431420, produce_speed 61577, consume_speed 61671
produce_index 499569, consume_index 499469, produce_speed 68142, consume_speed 68049
produce_index 566527, consume_index 566525, produce_speed 66958, consume_speed 67056
produce_index 623756, consume_index 623755, produce_speed 57229, consume_speed 57230
produce_index 680323, consume_index 680324, produce_speed 56567, consume_speed 56569
produce_index 733719, consume_index 733685, produce_speed 53396, consume_speed 53361

如果不加

produce_index 5422483, consume_index 5422564, produce_speed 5421511, consume_speed 5421514
produce_index 14562113, consume_index 14562186, produce_speed 9140580, consume_speed 9140579
produce_index 24022788, consume_index 24022855, produce_speed 9460673, consume_speed 9460666
produce_index 32757889, consume_index 32757968, produce_speed 8735098, consume_speed 8735102
produce_index 40807901, consume_index 40807959, produce_speed 8050016, consume_speed 8050019
produce_index 49672649, consume_index 49672651, produce_speed 8864771, consume_speed 8864771
produce_index 58942749, consume_index 58942797, produce_speed 9270077, consume_speed 9270076
produce_index 66635910, consume_index 66635901, produce_speed 7693184, consume_speed 7693174
produce_index 74313103, consume_index 74313198, produce_speed 7677170, consume_speed 7677180
produce_index 85118007, consume_index 85118004, produce_speed 10804927, consume_speed 10804923
produce_index 94494103, consume_index 94494154, produce_speed 9376073, consume_speed 9376077