首頁  >  文章  >  Java  >  Java的堆疊和佇列實例分析

Java的堆疊和佇列實例分析

王林
王林轉載
2023-05-10 16:40:151325瀏覽

    堆疊

    package com.yuzhenc.collection;
    
    import java.util.Stack;
    
    /**
     * @author: yuzhenc
     * @date: 2022-03-20 15:41:36
     * @desc: com.yuzhenc.collection
     * @version: 1.0
     */
    public class Test26 {
        public static void main(String[] args) {
            Stack<String> stack = new Stack<>();
            stack.add("A");
            stack.add("B");
            stack.add("C");
            stack.add("D");
            System.out.println(stack);//[A, B, C, D]
            //判断栈是否为空
            System.out.println(stack.empty());//false
            //查看栈顶元素,不会移除
            System.out.println(stack.peek());//D
            System.out.println(stack);//[A, B, C, D]
            //查看栈顶元素,并且移除,即出栈(先进后出)
            System.out.println(stack.pop());//D
            System.out.println(stack);//[A, B, C]
            //入栈,和add方法执行的功能一样,就是返回值不同
            System.out.println(stack.push("E"));//返回入栈的元素 E
            System.out.println(stack);//[A, B, C, E]
        }
    }

    佇列

    #阻塞佇列

    • ArrayBlockingQueue : 不支援讀寫同時操作,底層基於數組的;

    • LinkedBlockingQueue:支援讀寫同時操作,並發情況下,效率高,底層基於鍊錶;

    package com.yuzhenc.collection;
    
    import java.util.concurrent.ArrayBlockingQueue;
    import java.util.concurrent.TimeUnit;
    
    /**
     * @author: yuzhenc
     * @date: 2022-03-20 16:00:22
     * @desc: com.yuzhenc.collection
     * @version: 1.0
     */
    public class Test27 {
        public static void main(String[] args) throws InterruptedException {
            ArrayBlockingQueue<String> arrayBlockingQueue = new ArrayBlockingQueue<>(3);
            //添加元素
            //不可以添加null,报空指针异常
            //arrayBlockingQueue.add(null);
            //arrayBlockingQueue.offer(null);
            //arrayBlockingQueue.put(null);
    
            //正常添加元素
            System.out.println(arrayBlockingQueue.add("Lili"));//true
            System.out.println(arrayBlockingQueue.offer("Amy"));//true
            arrayBlockingQueue.put("Nana");//无返回值
    
            //队列满的情况下添加元素
            //arrayBlockingQueue.add("Sam");//报非法的状态异常
            //设置最大注阻塞时间,如果时间到了队列还是满的,就不再阻塞了
            arrayBlockingQueue.offer("Daming", 3,TimeUnit.SECONDS);
            System.out.println(arrayBlockingQueue);//[Lili, Amy, Nana]
            //真正阻塞的方法,如果队列一直是满的,就一直阻塞
            //arrayBlockingQueue.put("Lingling");//运行到这永远走不下去了,阻塞了
    
            //获取元素
            //获取队首元素不移除
            System.out.println(arrayBlockingQueue.peek());//Lili
            //出队,获取队首元素并且移除
            System.out.println(arrayBlockingQueue.poll());//Lili
            System.out.println(arrayBlockingQueue);//[Amy, Nana]
            //获取队首元素,并且移除
            System.out.println(arrayBlockingQueue.take());//Amy
            System.out.println(arrayBlockingQueue);//[Nana]
    
            //清空元素
            arrayBlockingQueue.clear();
            System.out.println(arrayBlockingQueue);//[]
    
            System.out.println(arrayBlockingQueue.peek());
            System.out.println(arrayBlockingQueue.poll());
            //设置阻塞事件,如果队列为空,返回null,时间到了以后就不阻塞了
            System.out.println(arrayBlockingQueue.poll(2,TimeUnit.SECONDS));
            //真正的阻塞,队列为空
            //System.out.println(arrayBlockingQueue.take());//执行到这里走不下去了
        }
    }

    SynchronousQueue:方便且有效率地進行執行緒間資料的傳送,不會產生佇列中資料爭搶問題;

    package com.yuzhenc.collection;
    
    import java.util.concurrent.SynchronousQueue;
    
    /**
     * @author: yuzhenc
     * @date: 2022-03-20 21:06:47
     * @desc: com.yuzhenc.collection
     * @version: 1.0
     */
    public class Test28 {
        public static void main(String[] args) {
            SynchronousQueue sq = new SynchronousQueue();
            //创建一个线程,取数据:
            new Thread(new Runnable() {
                @Override
                public void run() {
                    while(true){
                        try {
                            System.out.println(sq.take());
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }).start();
            //搞一个线程,往里面放数据:
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        sq.put("aaa");
                        sq.put("bbb");
                        sq.put("ccc");
                        sq.put("ddd");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }
    }
    • PriorityBlockingQueue:帶有優先權的阻塞佇列;

    • 無界的佇列,沒有長度限制,但是在你不指定長度的時候,預設初始長度為11,也可以手動指定,當然隨著資料不斷的加入,底層(底層是數組Object[])會自動擴容,直到記憶體全部消耗殆盡了,導致OutOfMemoryError記憶體溢位程式才會結束;

    • 不可以放入null元素的,不允許放入不可比較的物件(導致拋ClassCastException),物件必須實作內部比較器或外部比較器;

    package com.yuzhenc.collection;
    
    import java.util.concurrent.PriorityBlockingQueue;
    
    /**
     * @author: yuzhenc
     * @date: 2022-03-20 21:16:56
     * @desc: com.yuzhenc.collection
     * @version: 1.0
     */
    public class Test29 {
        public static void main(String[] args) throws InterruptedException {
            PriorityBlockingQueue<Human> priorityBlockingQueue = new PriorityBlockingQueue<>();
            priorityBlockingQueue.put(new Human("Lili",25));
            priorityBlockingQueue.put(new Human("Nana",18));
            priorityBlockingQueue.put(new Human("Amy",38));
            priorityBlockingQueue.put(new Human("Sum",9));
            //没有按优先级排列
            System.out.println(priorityBlockingQueue);//[Human{name=&#39;Sum&#39;, age=9}, Human{name=&#39;Nana&#39;, age=18}, Human{name=&#39;Amy&#39;, age=38}, Human{name=&#39;Lili&#39;, age=25}]
            //出列的时候按优先级出列
            System.out.println(priorityBlockingQueue.take());//Human{name=&#39;Sum&#39;, age=9}
            System.out.println(priorityBlockingQueue.take());//Human{name=&#39;Nana&#39;, age=18}
            System.out.println(priorityBlockingQueue.take());//Human{name=&#39;Lili&#39;, age=25}
            System.out.println(priorityBlockingQueue.take());//Human{name=&#39;Amy&#39;, age=38}
        }
    }
    
    class Human implements Comparable <Human> {
        String name;
        int age;
    
        public Human() {}
    
        public Human(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        @Override
        public String toString() {
            return "Human{" +
                    "name=&#39;" + name + &#39;\&#39;&#39; +
                    ", age=" + age +
                    &#39;}&#39;;
        }
    
        @Override
        public int compareTo(Human o) {
            return this.age-o.age;
        }
    • DelayQueue:DelayQueue是一個無界的BlockingQueue,用於放置實現了Delayed介面的對象,其中的物件只能在其到期時才能從佇列中取走;

    • 當生產者執行緒呼叫put之類的方法加入元素時,會觸發Delayed介面中的compareTo方法進行排序,也就是說佇列中元素的順序是按到期時間排序的,而非它們進入佇列的順序。排在佇列頭部的元素是最早到期的,越往後到期時間越晚;

    • #消費者執行緒查看佇列頭部的元素,注意是查看不是取出。然後呼叫元素的getDelay方法,如果此方法傳回的值小0或等於0,則消費者執行緒會從佇列中取出此元素,並進行處理。如果getDelay方法傳回的值大於0,則消費者執行緒wait傳回的時間值後,再從佇列頭部取出元素,此時元素應該已經到期;

    • ##不能將null元素放置到這種佇列中;

    • DelayQueue能做什麼

      • 淘寶訂單業務:下單之後如果三十分鐘之內沒有付款就自動取消訂單;

      • 餓了嗎訂餐通知:下單成功後60s之後給用戶發送簡訊通知;

      • 關閉空閒連線。伺服器中,有許多客戶端的連接,空閒一段時間之後需要關閉之;

      • 快取。快取中的對象,超過了空閒時間,需要從快取中移出;

      • 任務逾時處理。在網路協定滑動視窗請求應答式互動時,處理逾時未回應的請求等;

      package com.yuzhenc.collection;
      
      import java.util.concurrent.DelayQueue;
      import java.util.concurrent.Delayed;
      import java.util.concurrent.TimeUnit;
      
      /**
       * @author: yuzhenc
       * @date: 2022-03-20 21:43:32
       * @desc: com.yuzhenc.collection
       * @version: 1.0
       */
      public class Test30 {
          //创建一个队列:
          DelayQueue<User> dq = new DelayQueue<>();
          //登录游戏:
          public void login(User user){
              dq.add(user);
              System.out.println("用户:[" + user.getId() +"],[" + user.getName() + "]已经登录,预计下机时间为:" + user.getEndTime() );
          }
          //时间到,退出游戏,队列中移除:
          public void logout(){
              //打印队列中剩余的人:
              System.out.println(dq);
              try {
                  User user = dq.take();
                  System.out.println("用户:[" + user.getId() +"],[" + user.getName() + "]上机时间到,自动退出游戏");
              } catch (InterruptedException e) {
                  e.printStackTrace();
              }
          }
          //获取在线人数:
          public int onlineSize(){
              return dq.size();
          }
          //这是main方法,程序的入口
          public static void main(String[] args) {
              //创建测试类对象:
              Test30 test = new Test30();
              //添加登录的用户:
              test.login(new User(1,"张三",System.currentTimeMillis()+5000));
              test.login(new User(2,"李四",System.currentTimeMillis()+2000));
              test.login(new User(3,"王五",System.currentTimeMillis()+10000));
              //一直监控
              while(true){
                  //到期的话,就自动下线:
                  test.logout();
                  //队列中元素都被移除了的话,那么停止监控,停止程序即可
                  if(test.onlineSize() == 0){
                      break;
                  }
              }
          }
      }
      class User implements Delayed {
          private int id;//用户id
          private String name;//用户名字
          private long endTime;//结束时间
          public int getId() {
              return id;
          }
          public void setId(int id) {
              this.id = id;
          }
          public String getName() {
              return name;
          }
          public void setName(String name) {
              this.name = name;
          }
          public long getEndTime() {
              return endTime;
          }
          public void setEndTime(long endTime) {
              this.endTime = endTime;
          }
          public User(int id, String name, long endTime) {
              this.id = id;
              this.name = name;
              this.endTime = endTime;
          }
          //只包装用户名字就可以
          @Override
          public String toString() {
              return "User{" +
                      "name=&#39;" + name + &#39;\&#39;&#39; +
                      &#39;}&#39;;
          }
          @Override
          public long getDelay(TimeUnit unit) {
              //计算剩余时间 剩余时间小于0 <=0  证明已经到期
              return this.getEndTime() - System.currentTimeMillis();
          }
          @Override
          public int compareTo(Delayed o) {
              //队列中数据 到期时间的比较
              User other = (User)o;
              return ((Long)(this.getEndTime())).compareTo((Long)(other.getEndTime()));
          }
      }

    Java的堆疊和佇列實例分析

    雙端佇列

    package com.yuzhenc.collection;
    
    import java.util.Deque;
    import java.util.LinkedList;
    
    /**
     * @author: yuzhenc
     * @date: 2022-03-20 22:03:36
     * @desc: com.yuzhenc.collection
     * @version: 1.0
     */
    public class Test31 {
        public static void main(String[] args) {
            /*
            双端队列:
            Deque<E> extends Queue
            Queue一端放 一端取的基本方法  Deque是具备的
            在此基础上 又扩展了 一些 头尾操作(添加,删除,获取)的方法
             */
            Deque<String> d = new LinkedList<>() ;
            d.offer("A");
            d.offer("B");
            d.offer("C");
            System.out.println(d);//[A, B, C]
            d.offerFirst("D");
            d.offerLast("E");
            System.out.println(d);//[D, A, B, C, E]
            System.out.println(d.poll());//D
            System.out.println(d);//[A, B, C, E]
            System.out.println(d.pollFirst());//A
            System.out.println(d.pollLast());//E
            System.out.println(d);//[B, C]
        }
    }

    以上是Java的堆疊和佇列實例分析的詳細內容。更多資訊請關注PHP中文網其他相關文章!

    陳述:
    本文轉載於:yisu.com。如有侵權,請聯絡admin@php.cn刪除