常見的執行緒模型
常見的執行緒模型
對於伺服器應用而言,無論是web應用服務還是DB服務,高併發請求始終是一個繞不開的話題當有大量請求併發訪問時,一定伴隨著資源的不斷建立和釋放,導致資源利用率低,降低了服務質量。
1、單執行緒伺服器程式設計模型
Redis
redis是單執行緒來處理命令的,所以一條命令從客戶端到到服務端不會立刻被執行,所有命令都回進入到一個佇列中,然後逐個執行。
Node.Js
Node.Js基於事件驅動的單執行緒非同步程式設計模型
JavaScript
JavaScript是一種單執行緒語言,所有任務都在一個執行緒上完成,即採用上面的第一種方法。一旦遇到大量任務或者遇到一個耗時的任務,網頁就會出現"假死",因為JavaScript停不下來,也就無法響應使用者的行為。
2. 多執行緒伺服器程式設計模型
併發多個執行緒,每條執行緒並行執行不同的任務。
執行緒的幾個主要概念
在多執行緒程式設計時,你需要了解以下幾個概念:
執行緒同步
執行緒間通訊
執行緒死鎖
執行緒控制:掛起、停止和恢復
3、主從多執行緒模式
兩個執行緒池
4、執行緒處理的核心資料類(阻塞佇列)
(1)單執行緒非同步程式設計
只要設定一個存放任務的阻塞佇列,讓一個工作執行緒每次從該佇列中取出一個任務並執行,完畢再取下一個任務
(2)執行緒池的實現原理
生產者—消費者模式
生產者消費者模式是通過一個容器來解決生產者和消費者的強耦合問題。生產者和消費者彼此之間不直接通訊,而通過阻塞佇列來進行通訊,所以生產者生產 完資料之後不用等待消費者處理,直接扔給阻塞佇列,消費者不找生產者要資料,而是直接從阻塞佇列裡取,阻塞佇列就相當於一個緩衝區,平衡了生產者和消費者 的處理能力。
核心資料型別(BlockingQueue)
BlockingQueue是java.util.concurrent包中的介面,擴充套件了java.util中的的Queue介面。
在Java8的API中,這個介面有11個public方法,5/6個實現類
既然是阻塞佇列,那麼它核心就是阻塞和喚醒,先看看其中兩個常用的實現類,以及它們之間的不同。
ArrayBlockingQueue
單鎖雙條件
在ArrayBlockingQueue實現中,take()和put()用的是統一的一個單鎖, 對於佇列“空”和“滿”的情況,分別使用了兩個Condition物件來維護。
資料元素是用Object[]來儲存的。對於take()和put()方法,則是分別使用了takeIndex和putIndex這兩個索引值來記錄存放資料的位置。
Put方法
LinkedBlockingQueue
雙鎖雙條件
在LinkedBlockingQueue類的實現中,是對put()和take()分別使用了兩個不同的鎖,都使用了ReentrantLock實現。而針對“空”和“滿”的阻塞條件,也是對這兩個所物件分別構建的兩個Condition物件(notEmpty和notFull),構成了雙鎖雙條件。
資料元素是node來儲存的。對於take()和put()方法,則是分別使用隊首node和隊尾node
來取數
Put方法