问题描述
实现生产者消费者算法,多个线程同时生产数据,多个线程同时消费数据,要求容量空间有上限,消费者和生产者需要相互等待。
解题思路
传统思路: 利用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