队列及其事例

队列

今天要给大家带来的是一期关于数据结构上的内容,队列;这里给大家模拟一个现实场景,昨天不是刚刚过2.14嘛,男同胞们会在奶茶店叫奶茶哦,2.14这天恰好人比较多,需要一个一个排队进行等候,在这里结合多线程给大家具体实现一个模型。

首先给大家实现一个循环队列的模型

大家需要具体从队列上了解,请上力扣队列 & 栈图文学 - LeetBook - 力扣(LeetCode)全球极客挚爱的技术成长平台

package Test.Date_23_2_12;

/**
 * @ClassName ArrayQueue
 * @Description TODO
 * @Author Pzy
 * @Date 2023/2/12 11:33
 * @Version 1.0
 **/
public class ArrayQueue {
    private int Front,Rear;//头尾指针
    private int maxSize;//最大容量
    private int QueueArr [];//给定一个存储数组
    private int Size;//容量

    //构造器
    public ArrayQueue(int k)
    {
        //创建存储数组
        this.maxSize = k;//把参数值传给当前对象的最大容量
        QueueArr = new int [maxSize];//创建容量为k的数组
        Front = -1;//初始化循环队列 头尾指针指向-1
        Rear = -1;
        Size = 0;//容量为0
    }

    //入列
    public boolean enQueue(int value){
        /*
        判断队列是否已满
        1、满了返回false
        2、未满
            1.判断队列是否已满,已满则返回false
            2.由于是循环队列头指针head需要知道具体位置(不一定在第一个元素的位置)
            所以需要判断head 是否 == -1 ,等于-1表示在最初的位置上(未改变)
            3.判断尾指针的位置是否在最后的位置(循环队列需要进行头尾指针的判断)
            尾指针在最后这说明,指向了第一个元素之前的位置
        尾指针 Rear+1 容量 Size+1
         */

        if(this.isFull()){
            return false;
        }
        if(this.Front == -1){this.Front = 0;}//说明在原来的位置上
        if(this.Rear == maxSize -1) {this.Rear =0;}//队列快满了
        else this.Rear++;//尾指针+1
        //一般插入情况
            this.Size++;//容量+1
            this.QueueArr[this.Rear] = value;//数据加入到数组当中
            return true;
    }

    //出列
    public boolean deQueue(){
        if(this.isEmpty()) return false;//判断是否为null
        if (this.Front == maxSize -1) this.Front =0;//判断头指针是否在最初的位置上
        else this.Front++;//头指针+1
        this.Size--;//出列容量减少
        return true;
    }

    //获取队首元素

	//判断队列是否为null
    public boolean isFull(){
        return this.Size == 0;
    }
    
    //判断队列是否已满
    public  boolean isEmpty() {
        return this.Size == maxSize;
    }


}

力扣队列代码

/**
 * @ClassName Queue
 * @Description TODO
 * @Author Love yue yue
 * @Date 2023/2/14 10:44
 * @Version 1.0
 **/
public class Queue {
    //队列
    private int [] data;
    private int head;//头指针
    private int tail;//尾指针
    private int size;//数组大小/容量

    //构造器
    public Queue(int k) {
        data = new int [k];//把参数中的值传入到int 数组需要给定的值当中
        head = -1;//头指针初始值
        tail = -1;//尾指针初始值
        size = k;//k值赋值给数组的容量值
    }

    //入列 队列尾部进入
    public boolean enQueue(int value){
        if(isFull() == true){
            return false;//如果数组已满 直接返回false
        }
        if(isEmpty() == true){
            head = 0;//如果数组位空,标记头指针的位置
        }
        tail = (tail+1)%size;
        /**
         *
         */
        data[tail]= value;//入列数据存储到尾指针指向的位置上  尾插法
        return true;
    }

    //出列 队列头部出列
    public boolean deQueue(){
        //判断队列是否位空 为空则返回false
        if(isEmpty() == true){
            return  false;
        }
        //头指针和尾指针的值相同的话,说明队列已经空了
        if(head == tail){
           head = -1;//头指针初始值
           tail = -1;//尾指针初始值
            return true;
        }
        //不满足以上情况说明队列没有满
        head = (head +1)%size;
        return true;

    }

    //从队列中获取第一项的值
    public int Front(){
        //判断是否为空,为空则返回false
        if(isEmpty() == true){
            return -1;//注意此处的返回值时int类型
        }
        //不为空则进行值的获取
        return data[head];
    }

    //从队列中获取最后第一项的值(和Front相似)
    public int Rear(){
        //判断是否为空,为空则返回false
        if(isEmpty() == true){
            return -1;
        }
        return data[tail];
    }


    //判断队列是否已满
    private boolean isFull() {
        //队列已满 ---- >
        return ((tail+1)%size) == head;
        /**
         * 当head == 0 tail = size-1 的时候 或者
         * head = tail +1
         * 这是队列是否已满的情况两情况(其实是一种)
         */
    }

    //判断队列是否已空
    private boolean isEmpty() {
        //队列为空 --->
        return head == -1;
    }

}

具体要实现一下功能(仿力扣写的功能目标)

  • MyCircularQueue(k): 构造器,设置队列长度为 k 。
  • Front: 从队首获取元素。如果队列为空,返回 -1 。
  • Rear: 获取队尾元素。如果队列为空,返回 -1 。
  • enQueue(value): 向循环队列插入一个元素。如果成功插入则返回真。
  • deQueue(): 从循环队列中删除一个元素。如果成功删除则返回真。
  • isEmpty(): 判断循环队列是否为空。
  • isFull():判断循环队列是否已满。

下面给大家写了一个使用循环队列和多线程的小Dome (生产者和消费者模型 — 不完整)

需求:有A B C 四个线程 采用流水线方式,A 处理完产品交给B,B处理完产品交给C,C处理完产品交给D

D处理完产品,结束任务。

需要处理的任务:

A处理时 num值增加20

​ num =num +20

B处理时当前num值乘10

​ num = num * 10

C处理时当前num值和当前num值相乘

​ num = num * num

/**
 * @ClassName Task
 * @Description TODO
 * @Author Love yue yue
 * @Date 2023/2/13 11:13
 * @Version 1.0
 **/
public class Task {
    int num;
    public  void taskA(){
        num += 20;
    }

    public  void taskB(){
        num *= 10;
    }

    public  void taskC(){
        num *=num;
    }
}

具体代码如下:

package Test.Date_23_2_13.Test02;

import java.util.LinkedList;

/**
 * @ClassName Joker
 * @Description TODO
 * @Author Love yue yue
 * @Date 2023/2/13 11:17
 * @Version 1.0
 **/
public class Joker {


    public static void main(String[] args) throws InterruptedException {
        LinkedList<Task> t1 = new LinkedList<Task>();
        LinkedList<Task> t2 = new LinkedList<Task>();
        LinkedList<Task> t3 = new LinkedList<Task>();
        LinkedList<Task> t4 = new LinkedList<Task>();


//        for (int i = 0; i < 50000; i++) {
        for (int i = 0; i < 500; i++) {
            t1.offer(new Task());
        }

        //启动线程
        Task task = new Task();

        synchronized (task){//在获取同一个对象锁的时候使用notify和wait
			//容量到达目标 启动A线程
            if(t1.size() == 500){
                new ThreadA_(t1,t2).start();
                
                //容量到达目标 结束A线程
                if(t2.size() == 500){
                    System.out.println("The A end");
                    return;
                }

            }
           }
        
        //监听线程
        //控制台打印
        new Thread(){
            //匿名内部类
            @Override
            public void run() {
                while(true){
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
					//获取当前的队列的容量
                    int asize = t1.size();
                    int bsize = t2.size();
                    int csize = t3.size();
                    int dsize = t4.size();
                    System.out.println("队列A:"+asize);
                    System.out.println("队列B:"+bsize);
                    System.out.println("队列C:"+csize);
                    System.out.println("队列D:"+dsize);
                    System.out.println();
                    
                    //处理B线程
                    synchronized (task) {
                        if (t2.size() == 500) {
                            new ThreadB_(t2, t3).start();
                            if(t3.size() == 500) {
                                System.out.println("The B end");
                            }
                        }
                    }
                    
                    //处理C线程
                    synchronized (task) {
                        if (t3.size() == 500) {
                            new ThreadC_(t3, t4).start();
                            if(t4.size() == 500) {
                                System.out.println("The C end");
                            }
                        }
                    }
                    //满足结束任务条件 结束任务
                    if(t1.size() == 0 && t2.size() == 0 && t3.size()==0 && t4.size() ==500){
                        return;
                    }
                }

            }
        }.start();
    }
}

//线程A
class ThreadA_ extends Thread{
    LinkedList<Task> t1;
    LinkedList<Task> t2;

    public ThreadA_(LinkedList<Task> t1, LinkedList<Task> t2) {
        this.t1 = t1;
        this.t2 = t2;
    }

    @Override
    public void run() {
//        while(true) {
        while(true) {
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            Task task = t1.poll();
            if(t1.size() == 0 && t2.size() == 500){//当线程t1和t2的容量达到相关值停止添加
                //此处处理顺序如果在调用方法之后会出现 取不到数据的 会发生NullPointerException异常
                break;
            }
            task.taskA();//调用taskA方法

            t2.offer(task);//添加

        }

    }
}

class ThreadB_ extends Thread{
    LinkedList<Task> t2;
    LinkedList<Task> t3;

    public ThreadB_(LinkedList<Task> t2, LinkedList<Task> t3) {
        this.t2 = t2;
        this.t3 = t3;
    }

    @Override
    public void run() {
        while(true) {
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            Task task = t2.poll();
            if (t2.size()==0 && t3.size() == 500) break;//处理方式和原理和A线程相似
            task.taskB();//调用taskB方法
            t3.offer(task);//添加到t3中
        }

    }


}

class ThreadC_ extends Thread{
LinkedList<Task> t3;
LinkedList<Task> t4;

    public ThreadC_(LinkedList<Task> t3, LinkedList<Task> t4) {
        this.t3 = t3;
        this.t4 = t4;
    }

    @Override
    public void run() {
        while(true){
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            Task task = t3.poll();
            if(t3.size()==0 && t4.size() == 500) return;//处理方式和原理和A线程相似
            task.taskC();//调用taskC方法
            t4.offer(task);//添加到t4中
        }
    }
}

由于本人目前能力有限,发现可能还有更好的方法去处理共享资源,后续会继续跟进的哦,期待大家的关注。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值