表面簡單實則暗藏玄機的面試題:Java數組適合做隊列嗎?

Java數組本身是一種線性數據結構,它可以用來存儲一系列固定大小的元素。盡管數組可以用于實現隊列的一些基本操作,比如入隊(enqueue)和出隊(dequeue),但由于其固定的大小,它并不適合直接作為通用的隊列使用。

隊列是一種先進先出(FIFO)的數據結構,它允許你在隊列的一端添加元素,在另一端移除元素。由于數組的長度是固定的,一旦數組滿了,你就不能繼續添加新的元素,除非你創建一個新的更大的數組并將現有元素復制過去。這種操作在隊列頻繁入隊和出隊時效率很低。

Java提供了Queue接口和實現了該接口的一些類,如LinkedList和PriorityQueue,這些都是更適合實現隊列的數據結構。LinkedList可以在兩端高效地添加和刪除元素,而PriorityQueue則可以按照元素的自然順序或者自定義的比較器來排序元素。

如果你需要一個簡單的隊列,并且知道隊列的大小是固定的,那么數組可能是一個選項。但在大多數實際應用場景中,使用LinkedList或PriorityQueue會是更好的選擇,因為它們提供了更多的靈活性和高效的動態調整能力。

假設我們有一個業務場景,需要處理一系列客戶服務請求,這些請求按照緊急程度(優先級)進行排序。緊急程度高的請求需要優先處理。我們可以使用PriorityQueue來存儲這些請求,并根據請求的緊急程度進行排序。同時,我們還可以使用LinkedList來記錄請求的處理順序,確保請求按照先進先出的原則被處理。

下面是一個簡單的示例代碼

import java.util.LinkedList;
import java.util.PriorityQueue;
import java.util.Comparator;// 客戶服務請求類
class CustomerRequest {private String requestId;private int priority; // 優先級,數值越小優先級越高public CustomerRequest(String requestId, int priority) {this.requestId = requestId;this.priority = priority;}public String getRequestId() {return requestId;}public int getPriority() {return priority;}@Overridepublic String toString() {return "Request [id=" + requestId + ", priority=" + priority + "]";}
}// 比較器,用于確定優先級順序
class RequestComparator implements Comparator<CustomerRequest> {@Overridepublic int compare(CustomerRequest r1, CustomerRequest r2) {return Integer.compare(r1.getPriority(), r2.getPriority());}
}public class CustomerServiceQueue {private PriorityQueue<CustomerRequest> priorityQueue;private LinkedList<CustomerRequest> processingQueue;public CustomerServiceQueue() {// 初始化優先隊列,使用自定義的比較器priorityQueue = new PriorityQueue<>(new RequestComparator());processingQueue = new LinkedList<>();}// 添加請求到優先隊列public void addRequest(CustomerRequest request) {priorityQueue.add(request);processingQueue.add(request); // 同時添加到處理隊列}// 處理請求public void processRequests() {while (!priorityQueue.isEmpty()) {// 從優先隊列中獲取最高優先級的請求CustomerRequest request = priorityQueue.poll();// 處理請求handleRequest(request);}}// 處理單個請求的方法private void handleRequest(CustomerRequest request) {System.out.println("Processing request: " + request);// 這里可以添加實際處理請求的代碼}public static void main(String[] args) {CustomerServiceQueue serviceQueue = new CustomerServiceQueue();// 添加一些請求serviceQueue.addRequest(new CustomerRequest("1", 3));serviceQueue.addRequest(new CustomerRequest("2", 1));serviceQueue.addRequest(new CustomerRequest("3", 2));// 處理請求serviceQueue.processRequests();}
}

在這個例子中,我們創建了一個CustomerRequest類來表示客戶服務請求,每個請求都有一個唯一的requestId和一個表示緊急程度的priority。我們定義了一個RequestComparator比較器來告訴PriorityQueue如何根據優先級來排序請求。

在CustomerServiceQueue類中,我們維護了一個PriorityQueue來存儲按優先級排序的請求,以及一個LinkedList來記錄請求的處理順序。當我們添加請求時,我們同時將請求添加到兩個隊列中。處理請求時,我們從PriorityQueue中取出最高優先級的請求,并調用handleRequest方法來處理它。

在main方法中,我們創建了一個CustomerServiceQueue實例,添加了一些請求,并調用了processRequests方法來處理它們。這樣,請求將按照優先級順序進行處理,同時保持了它們進入隊列的原始順序。

V哥說了,劇情該反轉了!

ArrayBlockingQueue

ArrayBlockingQueue 是 Java 中的一個線程安全的阻塞隊列實現,它內部使用一個固定大小的數組來存儲元素。其實現原理基于循環數組(通常稱為“環形緩沖區”或“循環緩沖區”),并使用兩個指針(takeIndex 和 putIndex)來分別追蹤隊列的頭和尾。

實現原理:

  • 循環數組:ArrayBlockingQueue 使用一個循環數組來存儲元素。這意味著數組的末尾與開頭是相鄰的,當指針移動到數組末尾時,它會“環繞”回到數組的開始。

  • 兩個指針:ArrayBlockingQueue 使用兩個指針來追蹤隊列的頭和尾。takeIndex 指向下一個被取出的元素,而 putIndex 指向下一個被插入的元素。

  • 鎖和條件變量:為了實現線程安全,ArrayBlockingQueue 使用一個單一的鎖(ReentrantLock)來控制同時只有一個線程可以進行入隊或出隊操作。同時,它還使用了兩個條件變量(notEmpty 和 notFull),分別用于在隊列為空或已滿時掛起線程。

  • 阻塞操作:當隊列為空時,出隊操作(take)的線程會被掛起,直到隊列中有新的元素被插入;當隊列已滿時,入隊操作(put)的線程會被掛起,直到隊列中有空間可用。

應用場景:

ArrayBlockingQueue 由于其線程安全和阻塞特性,適用于以下場景:

  • 生產者-消費者模式:這是最典型的應用場景,多個生產者線程向隊列中添加元素,多個消費者線程從隊列中取出元素。

  • 工作隊列:在多線程環境中,ArrayBlockingQueue 可以用作一個工作隊列,線程池中的線程從隊列中獲取任務進行處理。

  • 有限資源的管理:當需要管理有限數量的資源時,如數據庫連接池,ArrayBlockingQueue 可以確保資源的使用不超過限制。

  • 消息傳遞:在消息傳遞系統中,ArrayBlockingQueue 可以用作消息隊列,確保消息的順序性和可靠性。

示例代碼:

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;public class ArrayBlockingQueueExample {public static void main(String[] args) {// 創建一個有界隊列,容量為10BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(10);// 生產者線程new Thread(() -> {try {for (int i = 0; i < 20; i++) {queue.put(i);System.out.println("Produced: " + i);}} catch (InterruptedException e) {e.printStackTrace();}}).start();// 消費者線程new Thread(() -> {try {for (int i = 0; i < 20; i++) {int value = queue.take();System.out.println("Consumed: " + value);}} catch (InterruptedException e) {e.printStackTrace();}}).start();}
}

在這個示例中,我們創建了一個容量為10的 ArrayBlockingQueue。兩個線程分別模擬生產者和消費者。生產者嘗試向隊列中添加20個元素,而消費者則嘗試從隊列中取出20個元素。由于隊列容量有限,生產者在隊列滿時會阻塞,直到消費者取出元素釋放空間。同樣,消費者在隊列空時會阻塞,直到生產者添加新元素。

最后

所以,V哥想說,這個問題不是直接回答可以還是不可以,而具體問題具體分析,面試官通過通過一個問題切入,來了解面試者的技術掌握的面與深度。關注威哥愛編程,一起技術成長。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/13889.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/13889.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/13889.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

開關電源重點可靠性測試項目與測試方法

為確保開關電源在復雜工作環境下的安全性與穩定性&#xff0c;各種安全性測試成為不可或缺的環節。本文將深入探討幾項關鍵的安全性測試項目&#xff0c;幫助用戶全面了解如何評估開關電源的可靠性和安全性。 一、過壓保護測試方法 目的是為了檢測當輸出電壓過高時&#xff0c;…

Unity限制鼠標光標位置

限制鼠標光標位置 private void Awake() {Cursor.lockState CursorLockMode.Confined;//Cursor.visible false;隱藏鼠標光標 }●Confined&#xff1a;限制光標到游戲窗口。 ●Locked&#xff1a;鎖定光標到游戲窗口的中心并隱藏。 ●None&#xff1a;不被修改。

項目9-網頁聊天室2(登錄)

0.前端知識儲備 Ajax請求中的async:false/true的作用 - front-gl - 博客園 (cnblogs.com) 01.前端頁面展示 02.后端代碼 2.1 CONTROLLER RequestMapping("/login")public Result login(String username, String password, HttpSession httpSession){User user …

鄉村振興與農村社會治理現代化:加強農村社會治理體系和治理能力現代化建設,提升鄉村治理效能,為美麗鄉村建設提供堅實保障

一、引言 在全面推進鄉村振興的偉大實踐中&#xff0c;農村社會治理現代化是不可或缺的重要一環。隨著時代的發展&#xff0c;傳統的農村社會治理方式已經無法滿足現代社會發展的需求。因此&#xff0c;加強農村社會治理體系和治理能力現代化建設&#xff0c;提升鄉村治理效能…

2024年電工杯數學建模競賽思路資料匯總貼

下文包含&#xff1a;2024電工杯&#xff08;電工杯數學建模競賽&#xff09;思路解析、電工杯參賽時間及規則信息說明、好用的數模技巧及如何備戰數學建模競賽 C君將會第一時間發布選題建議、所有題目的思路解析、相關代碼、參考文獻、參考論文等多項資料&#xff0c;幫助大家…

深度學習(文章鏈接匯總)

神經網絡與深度學習-簡要入門 動手學深度學習-pytorch版本&#xff08;一&#xff09;&#xff1a;引言 & 預備知識 動手學深度學習-pytorch版本&#xff08;二&#xff09;&#xff1a;線性神經網絡 YOLOv8 學習與環境配置

XSS漏洞

漏洞描述 XSS全名叫Cross Site Scripting(跨站腳本攻擊)因為簡寫和css同名所以改名為XSS&#xff0c;該漏洞主要利用javascript可以控制html&#xff0c;css&#xff0c;瀏覽器的行為從而惡意利用&#xff0c;當開發人員未對輸入的內容進行過濾或編碼時&#xff0c;惡意用戶在…

蒼穹外賣①

1.BeanUtils.copyProperties(orders,orderVO); BeanUtils.copyProperties 是 Java 中 Apache Commons BeanUtils 庫的一個方法&#xff0c;它用于將一個 Java Bean 的屬性復制到另一個 Java Bean。這個方法非常適合于對象之間的屬性復制&#xff0c;尤其是當源對象和目標對象的…

云服務器上部署Kubernetes集群(K8S)

master節點&#xff1a;master node節點&#xff1a;node1 由于是ubuntu系統&#xff0c;參考兩個博客配置 安裝vmware搭建k8s集群&#xff08;親試無坑&#xff09;-CSDN博客 該博客是centos系統&#xff0c;所以稍微有點區別結合另一篇博客一起參考 kubernetes集群…

scrapy進階(豆瓣新書速遞)(比亞迪)

scrapy數據建模與請求 學習目標&#xff1a; 應用 在scrapy項目中進行建模應用 構造Request對象&#xff0c;并發送請求應用 利用meta參數在不同的解析函數中傳遞數據scrapy構造post請求 1. 數據建模 通常在做項目的過程中&#xff0c;在items.py中進行數據建模 1.1 為什么建…

gt.qpa.xcb: could not connect to display : 1

報錯解釋&#xff1a; 這個錯誤通常發生在使用X11&#xff08;X Window System&#xff09;的Linux環境中&#xff0c;當嘗試啟動一個基于Qt平臺的應用程序時。錯誤信息表明程序無法連接到X服務器顯示設備&#xff0c;原因可能是沒有正確設置DISPLAY環境變量&#xff0c;或者用…

【Spring security】【pig】Note03-pig token令牌解析器過程

&#x1f338;&#x1f338; pig token令牌解析器過程 &#x1f338;&#x1f338; pig后端源碼 一、解析請求中的令牌值。 二、驗證令牌 內省并驗證給定的令牌&#xff0c;返回其屬性。返回映射表示令牌有效。 /*** author lengleng* date 2019/2/1 擴展用戶信息*/ publi…

Hot100-棧

20. 有效的括號 - 力扣&#xff08;LeetCode&#xff09; class Solution {public boolean isValid(String s) {//用map的鍵值對匹配左右括號//按照順序&#xff0c;先匹配的是左括號&#xff0c;所以棧里面放左括號HashMap<Character, Character> rlationship new Has…

deepinlinuxv23b3用lazarus3.2開發生成2維碼

下載&#xff1a; https://sourceforge.net/projects/lazarus/files/ 最新版3.2.2的fpc,3.2的lazarus sourceforge默認下載慢&#xff0c;選擇auto-select能夠選擇近的鏡像站點&#xff0c;還不行的話也能夠motrix下載會自動更換域名 linux的qrencode安裝是 sudo apt…

跨境小白shopee被封號的原因?如何有效預防?

提到跨境電商平臺&#xff0c;大家都知道亞馬遜、Temu、TikTok shop這些是比較大的電商平臺。但最近幾年&#xff0c;在東南亞市場上&#xff0c;Shopee蝦皮卻是頗負盛名的一個跨境電商平臺&#xff0c;這也讓眾多中國跨境小白蜂擁而至。目前shopee的商家正在不斷增多&#xff…

[力扣題解] 130. 被圍繞的區域

題目&#xff1a;130. 被圍繞的區域 思路 代碼 Method 1 : 深度優先搜索&#xff0c;自己寫的 class Solution { private:int dir[4][2] {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};void dfs(vector<vector<char>>& board, vector<vector<bool>>&am…

vue3第三十四節(TS 之 interface 與 type 的異同)

1、interface 接口只能定義描述對象類型 如&#xff1a; interface PersonIn {name: string;age:number;job:string; }// 定義函數 interface FPerson {(a: number, b:string) > void }2、類型別名 type則可以定義多種類型 如&#xff1a; type userName string type…

DeepDriving | CUDA編程-02: 初識CUDA編程

本文來源公眾號“DeepDriving”&#xff0c;僅用于學術分享&#xff0c;侵權刪&#xff0c;干貨滿滿。 原文鏈接&#xff1a;CUDA編程-02&#xff1a; 初識CUDA編程 上一篇文章DeepDriving | CUDA編程-01&#xff1a; 搭建CUDA編程環境-CSDN博客介紹了如何搭建CUDA編程環境&a…

選擇、快排、堆排序、歸并

選擇排序 排序的核心是&#xff1a;在未排序的序列中&#xff0c;把未排序第一個元素和未排序的最小元素交換位置。 因此&#xff0c;設計時&#xff0c;顯然要設置兩重 for 循環 假設未排序的第一個元素稱為 a &#xff0c; 未排序的最小元素稱為 b 第一重 for 循環控制總…

web壓力測試,要不要過濾掉JS,CSS等請求?

在進行性能測試&#xff08;壓測&#xff09;時&#xff0c;是否過濾掉對JavaScript、CSS等靜態資源的請求&#xff0c;取決于你測試的目標和目的。 是測試服務端的性能還是前端的性能。這兩種目的所涉及到的測試場景和工具等方法是不一樣的。 一般的web產品&#xff0c;像cs…