生产者/消费者模型的实现

文章目录

  • 一、生产者消费者模型实现
    • 1. wait/notify/notifyAll实现
    • 2. await/signal/signalAll
    • 3. 利用BlockingQueue来实现
    • 4. 总结

一、生产者消费者模型实现

1. wait/notify/notifyAll实现

注意线程中的判断使用while判断,不用if判断!

public class ConsumerAndProductor {
    final LinkedList<Integer> container = new LinkedList();
    final static int MAX = 10;
    static int size;// 容量

    public int getCount() {
        return size;
    }

    public synchronized void pruduct() {
        while (getCount() == MAX) {
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        // 不成立的话
        size++;
        container.add(size);
        System.out.println("container has producted 1, size=" + size);
        this.notifyAll();
    }

    public synchronized void consumer() {
        // 生产者要与消费者配套执行,否则不可执行
        while (getCount() == 0) {
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        size--;
        container.removeFirst();// 消费一个
        System.out.println("container has consumerd 1, size=" + size);
        this.notifyAll();
    }

    public static void main(String[] args) {
        ConsumerAndProductor cp = new ConsumerAndProductor();
        for (int i = 0; i < 10; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    for (int i = 0; i < 5; i++) {
                        cp.consumer();
                    }
                }
            }).start();
        }
        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        for (int i = 0; i < 2; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    for (int j = 0; j < 25; j++) {

                        cp.pruduct();
                    }
                }
            }).start();
        }
    }
}

2. await/signal/signalAll

主要是利用JUC中的Condition条件来实现定点通知。

public class ConsumerAndProductII {
    final LinkedList<Integer> container = new LinkedList<>();
    final Lock lock = new ReentrantLock();
    final Condition consumerCondition = lock.newCondition();
    final Condition producterCondition = lock.newCondition();
    final static int MAX = 10;
    static int size;// 容量

    public int getCount() {
        return size;
    }

    public void product() {
        // 生产者
        try {
            // 获取到当前锁
            lock.lock();
            while (this.getCount() == MAX) {
                try {
                    // 到达最大的容量就不生产
                    producterCondition.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            size++;
            int anInt = new Random().nextInt(100);
            System.out.println("生产者生产产品:" + anInt);
            container.add(anInt);
            // 这样的话,可以实现定点推送任务
            consumerCondition.signal();
        } finally {
            // 释放锁
            lock.unlock();
        }
    }

    public void consumer() {
        // 生产者
        try {
            // 获取到当前锁
            lock.lock();
            while (this.getCount() == 0) {
                try {
                    // 到达最大的容量就不生产
                    consumerCondition.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            size--;
            Integer remove = container.remove();
            System.out.println("消费者消费产品:" + remove);
            // 这样的话,可以实现定点推送任务
            producterCondition.signal();
        } finally {
            // 释放锁
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        ConsumerAndProductII cp = new ConsumerAndProductII();
        for (int i = 0; i < 10; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    for (int i = 0; i < 5; i++) {
                        cp.consumer();
                    }
                }
            }).start();
        }
        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        for (int i = 0; i < 2; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    for (int j = 0; j < 25; j++) {

                        cp.product();
                    }
                }
            }).start();
        }
    }
}

3. 利用BlockingQueue来实现

主要是利用ArrayBlockingQueue阻塞队列来实现。

class MyResouce {
    // 标志位
    private volatile boolean FLAG = true;
    // 运算的原子类
    private AtomicInteger atomicInteger = new AtomicInteger();
    // 阻塞队列
    private BlockingQueue<String> blockingQueue = null;

    // 阻塞队列是不定的,在构造器中传入可以适应多样的阻塞队列
    public MyResouce(BlockingQueue<String> blockingQueue) {
        this.blockingQueue = blockingQueue;
        System.out.println(blockingQueue.getClass().getName());
    }

    public void prod() {
        String data = null;
        boolean retValue;
        // 为真的时候,此时生产
        while (FLAG) {
            // 获取生产的数据
            data = atomicInteger.incrementAndGet() + "";
            try {
                retValue = blockingQueue.offer(data, 2L, TimeUnit.SECONDS);
                if (retValue) {
                    // 如果为真的话,表名插入成功
                    System.out.println(Thread.currentThread().getName() + "\t 插入队列" + data + "成功");
                } else {
                    System.out.println(Thread.currentThread().getName() + "\t 插入队列失败");
                }
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println(Thread.currentThread().getName() + "\t 主线程叫停了,停止生产,FLAG=false");
    }

    public void consume() {
        String result = null;
        while (FLAG) {
            try {
                result = blockingQueue.poll(2L, TimeUnit.SECONDS);
                if (result == null || result.equalsIgnoreCase("")) {
                    FLAG = false;
                    System.out.println(Thread.currentThread().getName() + "\t 超过2秒钟没有发现有产品可消费,消费退出.....");
                    System.out.println();
                    System.out.println();
                    return;
                }
                System.out.println(Thread.currentThread().getName() + "\t 消费产品" + result + "成功!");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public void stop() {
        this.FLAG = false;
    }
}

public class ConsumerAndProductIII {
    public static void main(String[] args) {
        MyResouce myResouce = new MyResouce(new ArrayBlockingQueue<>(10));
        new Thread(() -> {
            System.out.println("生产者线程启动!");
            myResouce.prod();
        }, "Product").start();

        new Thread(() -> {
            System.out.println("消费者线程启动!");
            System.out.println();
            System.out.println();
            myResouce.consume();
        }, "Consume").start();

        try {
            TimeUnit.SECONDS.sleep(5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println();
        System.out.println();
        System.out.println();
        System.out.println("5秒钟时间到,主线程叫停!");
        myResouce.stop();
    }
}

4. 总结

记住:线程 操作 资源类!

你可能感兴趣的:(面试复习指南)