package org.bigbird.researcher.collection.test;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.stream.Stream;
//需求:N个生产者线程、M个消费者线程、仓库容量为X,生产消费过程遵循FIFO,禁止使用concurrent包,只能使用非线程安全的数据结构,
// 并自己实现并发控制。一小时实现 start 2018/11/5 11:00
public class QueueTest {
private List<Thread> produceThread;//生产者线程
private List<Thread> consumerThread;//消费者线程
//仓库队列
private final Queue<Integer> repositoryQueue;
//可运行标志
private volatile boolean runFlag = true;
public QueueTest(int repositorySize, int produceNum, int consumerNum) {
this.repositoryQueue = synchronizedQueue(new ArrayDeque<>(repositorySize), repositorySize);
buildProduceThread(produceNum);
buildConsumerThread(consumerNum);
}
static class SynchronizedCollection<E> implements Collection<E>, Serializable {
final Collection<E> c; // Backing Collection
final Object mutex; // Object on which to synchronize
SynchronizedCollection(Collection<E> c) {
this.c = Objects.requireNonNull(c);
mutex = this;
}
SynchronizedCollection(Collection<E> c, Object mutex) {
this.c = Objects.requireNonNull(c);
this.mutex = Objects.requireNonNull(mutex);
}
public int size() {
synchronized (mutex) {return c.size();}
}
public boolean isEmpty() {
synchronized (mutex) {return c.isEmpty();}
}
public boolean contains(Object o) {
synchronized (mutex) {return c.contains(o);}
}
public Object[] toArray() {
synchronized (mutex) {return c.toArray();}
}
public <T> T[] toArray(T[] a) {
synchronized (mutex) {return c.toArray(a);}
}
public Iterator<E> iterator() {
return c.iterator(); // Must be manually synched by user!
}
public boolean add(E e) {
synchronized (mutex) {return c.add(e);}
}
public boolean remove(Object o) {
synchronized (mutex) {return c.remove(o);}
}
public boolean containsAll(Collection<?> coll) {
synchronized (mutex) {return c.containsAll(coll);}
}
public boolean addAll(Collection<? extends E> coll) {
synchronized (mutex) {return c.addAll(coll);}
}
public boolean removeAll(Collection<?> coll) {
synchronized (mutex) {return c.removeAll(coll);}
}
public boolean retainAll(Collection<?> coll) {
synchronized (mutex) {return c.retainAll(coll);}
}
public void clear() {
synchronized (mutex) {c.clear();}
}
public String toString() {
synchronized (mutex) {return c.toString();}
}
// Override default methods in Collection
@Override
public void forEach(Consumer<? super E> consumer) {
synchronized (mutex) {c.forEach(consumer);}
}
@Override
public boolean removeIf(Predicate<? super E> filter) {
synchronized (mutex) {return c.removeIf(filter);}
}
@Override
public Spliterator<E> spliterator() {
return c.spliterator(); // Must be manually synched by user!
}
@Override
public Stream<E> stream() {
return c.stream(); // Must be manually synched by user!
}
@Override
public Stream<E> parallelStream() {
return c.parallelStream(); // Must be manually synched by user!
}
private void writeObject(ObjectOutputStream s) throws IOException {
synchronized (mutex) {s.defaultWriteObject();}
}
}
static class SynchronizedQueue<E>
extends SynchronizedCollection<E>
implements Queue<E> {
final Queue<E> queue;
//队列容量(采用不扩容策略)
private final int repositorySize;
SynchronizedQueue(Queue<E> queue, int repositorySize) {
super(queue);
this.repositorySize = repositorySize;
this.queue = queue;
}
SynchronizedQueue(Queue<E> queue, int repositorySize, Object mutex) {
super(queue, mutex);
this.repositorySize = repositorySize;
this.queue = queue;
}
public boolean equals(Object o) {
if (this == o)
return true;
synchronized (mutex) {return queue.equals(o);}
}
public int hashCode() {
synchronized (mutex) {return queue.hashCode();}
}
@Override
public boolean offer(E e) {
synchronized (mutex) {
if(queue.size() >= repositorySize) {
return false;
} else {
return queue.offer(e);
}
}
}
@Override
public E remove() {
synchronized (mutex) {return queue.remove();}
}
@Override
public E poll() {
synchronized (mutex) {return queue.poll();}
}
@Override
public E element() {
synchronized (mutex) {return queue.element();}
}
@Override
public E peek() {
synchronized (mutex) {return queue.peek();}
}
}
public static <T> Queue<T> synchronizedQueue(Queue<T> queue, int repositorySize) {
return new SynchronizedQueue<>(queue, repositorySize);
}
//构建生产者线程
private void buildProduceThread(int produceNum) {
produceThread = new ArrayList<>(produceNum);
for (int i = 0; i < produceNum; i++) {
produceThread.add(new Thread(() -> {
try {
while (runFlag) {
//如果仓库队列已满,对生产者阻塞一段时间(也可以根据需求在此处使用拒绝策略)
int nextInt = new Random().nextInt(10000);
while (runFlag && !repositoryQueue.offer(nextInt)) {
System.out.println(Thread.currentThread().getName() + " : " + "队列已满,等待生产!");
Thread.sleep(100);
}
System.out.println(Thread.currentThread().getName() + " : " + "我生产了一个随机数 : " + nextInt);
Thread.sleep(100);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}));
}
}
//构建消费者线程
private void buildConsumerThread(int consumerNum) {
consumerThread = new ArrayList<>(consumerNum);
for (int i = 0; i < consumerNum; i++) {
consumerThread.add(new Thread(() -> {
try {
while (runFlag) {
Integer poll = repositoryQueue.poll();
System.out.println(poll == null ? "仓库中已无数字可消费!" : Thread.currentThread().getName() + " : " + "我从仓库中消费了一个数字 : " + poll);
Thread.sleep(200);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}));
}
}
public void start() {
produceThread.forEach(Thread::start);
consumerThread.forEach(Thread::start);
}
public void stop() {
this.runFlag = false;
}
public static void main(String[] args) throws InterruptedException {
final int N = 10;//生产者线程数
final int M = 20;//消费者线程数
final int X = 63;//仓库容量
QueueTest queueTest = new QueueTest(X, N, M);
queueTest.start();
//设置程序运行时间
Thread.sleep(1000);
queueTest.stop();
}
}
//end 2018/11/5 11:54
//modify in 12:30