zoukankan      html  css  js  c++  java
  • 生产者消费者模型

    生产者消费者模型当中有三个实体,他们分别是:

    生产者

    消费者

    缓冲队列

    缓冲队列要求:

    1.当缓冲队列为空时,不能往外取

    2.当缓冲队列为满时,不能继续往里添加

    对于缓冲队列的选择,可以选择线程安全的和线程非安全的.

    线程安全的类 ,指的是类内共享的全局变量的访问必须保证是不受多线程形式影响的。如果由于多线程的访问(比如修改、遍历、查看)而使这些变量结构被破坏或者针对这些变量操作的原子性被破坏,则这个类就不是线程安全的。

    线程不安全的包括:ArrayList.LinkedList等

    线程安全的包括:LinkedBlockingQueue,ArrayBlockingQueue等

    下面我们用线程不安全的LinkedList进行实验,看代码

    缓冲队列内要加入的元素类

    public class Task
    {
    
    }

    生产者类

    class Producer implements Runnable
    {
        private final Queue<Task> queue;
        private final static int MAX_SIZE = 2;
    
        Producer(Queue<Task> q)
        {
            queue = q;
        }
    
        public void run()
        {
            synchronized (queue)
            {
                //如果缓冲区满,该线程释放queue锁,等待
                while (queue.size() >= MAX_SIZE)
                {
                    try
                    {
                        queue.wait();
                    }
                    catch (InterruptedException e)
                    {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                //如果缓冲区不满,则继续添加任务
                queue.add(new Task());
                System.out.println("增加了一个任务,当前任务总数为" + queue.size());
                //添加任务以后,通知所有处于等待状态的线程
                queue.notifyAll();
            }
        }
    }

    消费者类

    class Consumer implements Runnable
    {
        private final Queue<Task> queue;
    
        Consumer(Queue<Task> q)
        {
            queue = q;
        }
    
        public void run()
        {
            synchronized (queue)
            {
                //如果缓冲区内为空,消费者释放queue对象锁,处于等待状态
                while (queue.size() <= 0)
                {
                    try
                    {
                        queue.wait();
                    }
                    catch (InterruptedException e)
                    {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                //如果缓冲区不为空,消费者将队首元素取走
                queue.remove();
                System.out.println("执行了一个任务,剩余任务总数为" + queue.size());
                //取走后通知所有处于等待状态的线程
                queue.notifyAll();
            }
        }
    }

    主函数类

    class Setup
    {
        public static void main(String args[])
        {
            Queue q = new LinkedList();
            Producer p = new Producer(q);
            Producer p1 = new Producer(q);
            Producer p2 = new Producer(q);
            Producer p3 = new Producer(q);
            Consumer c1 = new Consumer(q);
            Consumer c2 = new Consumer(q);
            new Thread(p).start();
            new Thread(p1).start();
            new Thread(p2).start();
            new Thread(c1).start();
            new Thread(c2).start();
        }
    }

    执行结果:

    增加了一个任务,当前任务总数为1
    增加了一个任务,当前任务总数为2
    执行了一个任务,剩余任务总数为1
    增加了一个任务,当前任务总数为2
    执行了一个任务,剩余任务总数为1

  • 相关阅读:
    Windows 8(64位)如何搭建 Android 开发环境与真机测试(转)
    C# winform写入和读取TXT文件
    winform利用ImageList控件和ListView控件组合制作图片文件浏览器
    Linux 桌面玩家指南:01. 玩转 Linux 系统的方法论
    这些年一直记不住的 Java I/O
    深入理解 JavaScript,以及 Linux 下的开发调试工具
    在 Ubuntu 中使用 Visual Studio Code
    像黑客一样使用 Linux 命令行
    JAAS 是个什么梗
    Java 开发主流 IDE 环境体验
  • 原文地址:https://www.cnblogs.com/mu-tou-man/p/4840519.html
Copyright © 2011-2022 走看看