Java 实现调度算法 包括 FCFS(FIFO)、优先权排队、循环排队、加权公平排队(WFQ)
文章目錄
- 為什么要用調(diào)度算法?
- 調(diào)度算法
- 先來先服務(wù)(FCFS First-Come First-Server)
- 優(yōu)先權(quán)排隊(Priority Queuing)
- 循環(huán)排隊(Round Queuing)
- 加權(quán)公平排隊(Weighted Fair Queuing)
- 加權(quán)輪詢
- 加權(quán)隨機(jī)
為什么要用調(diào)度算法?
首先要聲明這里實現(xiàn)的是應(yīng)用層調(diào)度算法,針對的是請求,而不是操作系統(tǒng)的進(jìn)程調(diào)度算法,在平常處理請求時,如果請求并發(fā)量不大,是一個接一個過來的,那我們沒有選擇只有一個接一個處理請求了,但是如果請求并發(fā)量很多,那我們就有選擇先執(zhí)行哪個請求的權(quán)力了,而選擇先執(zhí)行哪個請求就是調(diào)度算法,可以知道這里的請求都是我們要執(zhí)行的請求,只是執(zhí)行的順序先后不同而已,在這之前呢,會不會有要執(zhí)行的請求和被拒絕執(zhí)行的請求呢,也是有的,那個步驟叫做限流,可以看我這篇文章 漏桶(令牌桶)限流算法
調(diào)度算法
先來先服務(wù)(FCFS First-Come First-Server)
該算法也叫先進(jìn)先出 FIFO(First Input First Outer),這是非常公平的算法,實現(xiàn)也非常簡單,使用一個隊列,隊列中的節(jié)點可以有兩種構(gòu)成
下面實現(xiàn)使用第一種節(jié)點,而且節(jié)點里面只有一個請求的id信息,這樣最簡單
class Node {private int id;public Node(int id) {this.id = id;}@Overridepublic String toString() {return "Node{" +"id=" + id +'}';} } public class FCFSalgorithm {public static void main(String[] args) {Queue<Node> queue = new LinkedList<>();for (int i = 0; i < 10; i++) {queue.add(new Node(i));}while (!queue.isEmpty()) {Node poll = queue.poll();System.out.println("取出請求"+poll+"開始執(zhí)行任務(wù)");}} }優(yōu)先權(quán)排隊(Priority Queuing)
為什么會出現(xiàn)優(yōu)先權(quán)呢,難道公平不好嗎,這是因為特權(quán)用戶確實充了錢,所以我們得優(yōu)先處理它的請求,還是用上面的節(jié)點只是增加了優(yōu)先級priority屬性,實現(xiàn)方式有很多種如下:
下面使用第三種方式,因為這樣添加請求最簡單,請求先找到屬于自己的隊列,在隊尾添加即可
循環(huán)排隊(Round Queuing)
循環(huán)排隊也是公平的,為什么把不同的請求放入不同的隊列呢,可能因為它們屬于不同的類別,或者像我們排隊時可能有很多個窗口,每個窗口對應(yīng)一個隊列
實現(xiàn):根據(jù)每個請求的節(jié)點的類別把它放入不同的列表,然后循環(huán)隊列列表每個隊列一次只取出一個請求執(zhí)行,然后輪到下一個隊列,如果一個隊列為空,直接跳到下一個隊列
加權(quán)公平排隊(Weighted Fair Queuing)
回想一下我們上面的優(yōu)先級排隊,只有當(dāng)優(yōu)先級高的請求全部運行完了,才會運行下一優(yōu)先級的請求,這很明顯不符合社會主義核心價值觀,所以可以更加公平,讓氪金用戶不管氪多少,都只是增大他請求先運行的幾率,如果運氣好,普通用戶的請求也能在氪金用戶請求之前運行
實現(xiàn)方式:
仍然需要按優(yōu)先級把請求分到不同的隊列,每次也只拿出其中一個隊列的請求進(jìn)行處理,所以重點就在怎樣選擇這個隊列,有以下方式:
加權(quán)輪詢
根據(jù)用戶優(yōu)先級生成一個選擇列表,可以是一個數(shù)組,假如只有三個優(yōu)先級 0,1,2,那么數(shù)組可以為[0, 0, 0, 1, 1, 2] 這樣,表示先選擇三次0優(yōu)先級的隊列取出其中三個任務(wù)執(zhí)行,再選擇1優(yōu)先級的隊列取出其中兩個任務(wù)執(zhí)行,再選擇2優(yōu)先級的隊列取出其中一個任務(wù)執(zhí)行,如果0優(yōu)先級隊列沒有任務(wù)了,就找1優(yōu)先級隊列,如果1優(yōu)先級沒有了就找2優(yōu)先級隊列
class WNode {private int id;public int priority;public WNode(int id, int priority) {this.id = id;this.priority = priority;}@Overridepublic String toString() {return "WNode{" +"id=" + id +", priority=" + priority +'}';} }public class WeightedFairQueuingAlgorithm {public static void main(String[] args) {Queue<WNode>[] queueList = new Queue[3];for (int i = 0; i < 10; i++) {WNode wNode = new WNode(i, i % 3);if (queueList[wNode.priority] == null) {queueList[wNode.priority] = new LinkedList<>();}Queue<WNode> queue = queueList[wNode.priority];queue.add(wNode);}// 可以根據(jù)優(yōu)先級種類數(shù)動態(tài)構(gòu)建的int[] dispatch = new int[]{0,0,0,1,1,2};while (true) {boolean flag = true;for (int index : dispatch) {Queue<WNode> queue = queueList[index];if (!queue.isEmpty()) {flag = false;WNode poll = queue.poll();System.out.println("取出請求"+poll+"開始執(zhí)行任務(wù)");}}if (flag) break;}} }加權(quán)隨機(jī)
上面那種方式還是太固定了,對運氣好的普通用戶不公平,可以使用隨機(jī)數(shù),假設(shè)隨機(jī)數(shù)范圍為1-6,則隨機(jī)數(shù)是1-3三個數(shù)中一個,選擇0優(yōu)先級的隊列取出其中一個任務(wù)執(zhí)行,隨機(jī)數(shù)是4-5兩個數(shù)中一個,選擇1優(yōu)先級的隊列取出其中一個任務(wù)執(zhí)行,隨機(jī)數(shù)是6則選擇2優(yōu)先級的隊列取出其中一個任務(wù)執(zhí)行,也可以使用上面的數(shù)組,用隨機(jī)值作為下標(biāo)
class WNode {private int id;public int priority;public WNode(int id, int priority) {this.id = id;this.priority = priority;}@Overridepublic String toString() {return "WNode{" +"id=" + id +", priority=" + priority +'}';} }public class WeightedFairQueuingAlgorithm {public static void main(String[] args) {Queue<WNode>[] queueList = new Queue[3];for (int i = 0; i < 100; i++) {WNode wNode = new WNode(i, i % 3);if (queueList[wNode.priority] == null) {queueList[wNode.priority] = new LinkedList<>();}Queue<WNode> queue = queueList[wNode.priority];queue.add(wNode);}Random random = new Random();int[] dispatch = new int[]{0,0,0,1,1,2};while (true) {boolean flag = true;int i = random.nextInt(6);int priority = dispatch[i];// 循環(huán)是為了當(dāng)隨到的高優(yōu)先級隊列為空,可以往低優(yōu)先級隊列找請求for (int j = priority; j < 3; j++) {Queue<WNode> queue = queueList[j];if (!queue.isEmpty()) {flag = false;WNode poll = queue.poll();System.out.println("取出請求"+poll+"開始執(zhí)行任務(wù)");// 取出一個請求,跳出內(nèi)循環(huán),繼續(xù)執(zhí)行外循環(huán)break;}j++;}// 只有當(dāng)隨機(jī)到最高優(yōu)先級,// 而且把往后所有優(yōu)先級都找遍都沒到到請求才退出循環(huán)if (priority == 0 && flag) break;}} }總結(jié)
以上是生活随笔為你收集整理的Java 实现调度算法 包括 FCFS(FIFO)、优先权排队、循环排队、加权公平排队(WFQ)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 让Linux支持手机,让linux支持q
- 下一篇: Java 第十一届 蓝桥杯 省模拟赛