數據結構-隊列

簡單介紹

  • 隊列先進先出,相似一個隧道,先進的車先出隧道。數據庫

  • 做爲一種很是基礎的數據結構,隊列的應用也很是普遍,特別是一些具備某些額外特性的隊列,好比循環隊列、阻塞隊列、併發隊列。它們在不少偏底層系統、框架、中間件的開發中,起着關鍵性的做用。好比高性能隊列Disruptor、Linux環形緩存,都用到了循環併發隊 列;Java concurrent併發包利用ArrayBlockingQueue來實現公平鎖等。數組

  • 隊列和棧同樣,也是一種抽象的數據結構,用數組實現叫順序隊列,用鏈表實現叫鏈式隊列緩存

  • 隊列包含對頭(head),對尾(tail)安全

循環隊列

  • 首尾相連
  • image.png
  • 須要注意判斷隊空隊滿的臨界條件,當隊滿時,知足**(tail+1)%n=head **

阻塞隊列

  • 在隊列爲空的時候,從隊頭取數據會被阻塞。由於此時尚未數據可取,直到隊列中有了數據才能返回;若是隊列已經滿了,那麼插入數據的操做就會被阻塞,直到隊列中有空閒位置後再插入數據,而後再返回
  • image.png
  • 能夠使用阻塞隊列,輕鬆實現一個"生產者-消費者模型"
  • 能夠多建幾個消費者進行消費,在多線程狀況下就會產生併發問題,從而引出了併發隊列

image.png

併發隊列

  • 線程安全的隊列咱們叫做併發隊列
  • 最簡單直接的實現方式是直接在enqueue()、dequeue()方法上加鎖,可是鎖粒度大併發度會比較低,同一時刻僅容許一個存或者取操做。實際上,基於數組的循環隊列,利用CAS原子操做,能夠實現很是高效的併發隊列。這也是循環隊列比鏈式隊列應用更加普遍的緣由

線程池處理策略

  • 非阻塞的處理方式,直接拒絕任務請求數據結構

  • 將請求排隊,等到有空閒線程時,取出排隊的請求繼續處理多線程

  • 基於鏈表的實現方式,能夠實現一個支持無限排隊的無界隊列(unbounded queue),可是可能會致使過多的請求排隊等待,請求處理的響應時間過長。因此針對響應時間比較敏感的系統,基於鏈表實現的無限排隊的線程池是不合適的。併發

  • 基於數組實現的有界隊列(bounded queue),隊列的大小有限,因此線程池中排隊的請求超過隊列大小時,接下來的請求就會被拒絕,這種方式對響應時間敏感的系統來講,就相對更加合理。不過,設置一個合理的隊列大小,也是很是有講究的。隊列太大致使等待的請求太多,隊列過小會致使沒法充分利用系統資 源、發揮最大性能。框架

  • 除了前面講到隊列應用在線程池請求排隊的場景以外,隊列能夠應用在任何有限資源池中,用於排隊請求,好比數據庫鏈接池等。實際上,對於大部分資源有限的場景,當沒有空閒資源時,基本上均可以經過**「隊列」**這種數據結構來實現請求排隊。性能

相關文章
相關標籤/搜索