实现遵循FIFO的生产消费过程

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

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
[入门数据分析的第一堂课]这是一门为数据分析小白量身打造的课程,你从网络或者公众号收集到很多关于数据分析的知识,但是它们零散不成体系,所以第一堂课首要目标是为你介绍:Ø  什么是数据分析-知其然才知其所以然Ø  为什么要学数据分析-有目标才有动力Ø  数据分析的学习路线-有方向走得更快Ø  数据分析的模型-分析之道,快速形成分析思路Ø  应用案例及场景-分析之术,掌握分析方法[哪些同学适合学习这门课程]想要转行做数据分析师的,零基础亦可工作中需要数据分析技能的,例如运营、产品等对数据分析感兴趣,想要更多了解的[你的收获]n  会为你介绍数据分析的基本情况,为你展现数据分析的全貌。让你清楚知道自己该如何在数据分析地图上行走n  会为你介绍数据分析的分析方法和模型。这部分是讲数据分析的道,只有学会底层逻辑,能够在面对问题时有自己的想法,才能够下一步采取行动n  会为你介绍数据分析的数据处理和常用分析方法。这篇是讲数据分析的术,先有道,后而用术来实现你的想法,得出最终的结论。n  会为你介绍数据分析的应用。学到这里,你对数据分析已经有了初步的认识,并通过一些案例为你展现真实的应用。[专享增值服务]1:一对一答疑         关于课程问题可以通过微信直接询问老师,获得老师的一对一答疑2:转行问题解答         在转行的过程中的相关问题都可以询问老师,可获得一对一咨询机会3:打包资料分享         15本数据分析相关的电子书,一次获得终身学习
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值