• 处理机调度算法


    1. import java.util.*;
    2. class JCB {
    3. String name;// 进程名
    4. int arriveTime;// 到达时间
    5. int serveTime;// 服务时间
    6. int beginTime;// 开始时间
    7. int finishTime;// 结束时间
    8. int roundTime;// 周转时间
    9. double aveRoundTime;// 带权周转时间
    10. double clock = 0;// 在时间轮转调度算法中,记录该进程真实服务时间已经用时的时长
    11. int waitTime;// 记录每个进程到达后的等待时间,只用于最高响应比优先调度算法中
    12. boolean firstTimeTag = false;// 在RR算法中标识开始时间是否第一次计算
    13. public JCB(String name, int arriveTime, int serveTime, double waitTime) {
    14. this.name = name;
    15. this.arriveTime = arriveTime;
    16. this.serveTime = serveTime;
    17. this.waitTime = 0;
    18. }
    19. public String toString() {
    20. String info = new String("进程名:P" + this.name);
    21. return info;
    22. }
    23. }
    24. class processMenu {
    25. ArrayList jcb;// 存放所有进程
    26. LinkedList link;// 存放已经进入队列的进程
    27. ArrayList new_jcb;// 存放按指定调度算法排序后的进程
    28. JCB nowProess;// 当前应执行进程
    29. public void init() {// 初始化
    30. jcb = new ArrayList();
    31. link = new LinkedList();
    32. new_jcb = new ArrayList();
    33. JCB p1 = new JCB("1", 0, 4, 3);
    34. JCB p2 = new JCB("2", 1, 3, 2);
    35. JCB p3 = new JCB("3", 2, 5, 3);
    36. JCB p4 = new JCB("4", 3, 2, 1);
    37. JCB p5 = new JCB("5", 4, 4, 5);
    38. jcb.add(p1);
    39. jcb.add(p2);
    40. jcb.add(p3);
    41. jcb.add(p4);
    42. jcb.add(p5);
    43. // 先将jcb排序,便于下面的算法实现,就不需要再定义一个标识进程是否已到达的boolean,即无需每次都从头开始扫描jcb容器,
    44. // 而是用一个K记录下当前已经扫描到的位置,一次遍历即可,提高了算法效率。
    45. Collections.sort(jcb, new compareAt_St());
    46. }
    47. public void FCFS() {// 先来先服务算法
    48. ProcessQueue pq = new ProcessQueue();// 调用内部类
    49. pq.EnqueueLast();// 让最先到达的进程先入队
    50. System.out.println("*****************************************************");
    51. while (!link.isEmpty()) {// while(new_jcb.size()!=jcb.size())
    52. pq.DisplayQueue();// 打印当前队列中的进程
    53. pq.Dequeue();// 出队,一次一个
    54. pq.EnqueueLast();// 已到达的进程入队
    55. }
    56. }
    57. public void SJF() {// 短作业优先算法
    58. ProcessQueue pq = new ProcessQueue();
    59. pq.EnqueueLast();
    60. System.out.println("*****************************************************");
    61. while (!link.isEmpty()) {
    62. pq.DisplayQueue();// 打印当前队列中的进程
    63. pq.Dequeue();// 出队,一次一个
    64. pq.EnqueueLast();// 已到达的进程入队
    65. Collections.sort(link, new compareSt());// 队列中的进程还需按服务时间长度进行排序
    66. }
    67. }
    68. public void HRRN() {// 最高响应比优先调度算法
    69. ProcessQueue pq = new ProcessQueue();
    70. pq.EnqueueLast();
    71. System.out.println("*****************************************************");
    72. while (!link.isEmpty()) {
    73. pq.DisplayQueue();// 打印当前队列中的进程
    74. pq.Dequeue();// 出队,一次一个
    75. pq.EnqueueLast();// 已到达的进程入队
    76. Collections.sort(link, new comparePriority());// 队列中的进程还需按响应比进行排序
    77. }
    78. }
    79. class ProcessQueue {
    80. int k = 0;// jcb中的进程遍历时的下标
    81. int nowTime = 0;// 当前时间
    82. double sliceTime;// 轮转调度时间片
    83. int i = 0;// 记录当前出入队列的次数
    84. public void EnqueueLast() {// 进程首次入队,可一次进多个,从队尾进入
    85. while (k < jcb.size()) {// 当遍历完jcb中的所有进程时结束
    86. if (jcb.get(k).arriveTime <= nowTime) {// 已经到达的进程按到达时间先后进入队列
    87. link.addLast(jcb.get(k));
    88. k++;
    89. } else {
    90. break;// 如果该进程还未入队,即先结束遍历,保留当前下标k值,注意:此处不要k--;
    91. }
    92. }
    93. }
    94. public void EnqueueFirst() {// 进程首次入队,可一次进多个,从队首进入
    95. while (k < jcb.size()) {// 当遍历完jcb中的所有进程时结束
    96. if (jcb.get(k).arriveTime <= nowTime) {// 已经到达的进程按到达时间先后进入队列
    97. link.addFirst(jcb.get(k));
    98. k++;
    99. } else {
    100. break;// 如果该进程还未入队,即先结束遍历,保留当前下标k值,注意:此处不要k--;
    101. }
    102. }
    103. }
    104. public void Dequeue() {// 进程出队,一次只出一个
    105. nowProess = link.removeFirst();// 移除队列的队首元素并且返回该对象元素
    106. nowProess.beginTime = nowTime;// 计算开始时间,即为上一个进程的结束时间
    107. nowProess.finishTime = nowProess.beginTime + nowProess.serveTime;// 计算结束时间,该进程开始时间+服务时间
    108. nowProess.roundTime = nowProess.finishTime - nowProess.arriveTime;// 计算周转时间
    109. nowProess.aveRoundTime = (double) nowProess.roundTime / nowProess.serveTime;// 计算平均周转时间
    110. nowTime = nowProess.finishTime;// 获得结束时间,即当前时间,方便判断剩下的进程是否已到达
    111. new_jcb.add(nowProess);// 经处理过数据后加入new_jcb容器
    112. for (int i = 0; i < link.size(); ++i) {
    113. link.get(i).waitTime++;// 所有进入等待队列的进程等待时间+1,此处只为最高响应比算法所用
    114. }
    115. }
    116. public void Dequeue(double sliceTime) {// 重载Dequeue方法,实现轮转调度算法的出队
    117. nowProess = link.removeFirst();// 移除队列的队首元素并且返回该对象元素
    118. if (nowProess.firstTimeTag == false) {
    119. /*
    120. * 轮转调度进程可能会多次反复进出队列,不像FCFS和SJF的进程只会进出一次,所以计算开始时间可以设个标志位,让每个进程在
    121. * 第一次执行时记录一遍即可
    122. */
    123. nowProess.beginTime = nowTime;// 进程开始执行的时间
    124. nowProess.firstTimeTag = true;// 计算第一次即可,下次无需更新计算
    125. }
    126. nowTime += sliceTime;// 每次出队,用时一个时间片,更新当前时间
    127. nowProess.clock += sliceTime;// 更新当前出队列的进程已服务时间
    128. if (nowProess.clock >= nowProess.serveTime) {
    129. nowProess.finishTime = nowTime;// 计算该进程完成时间
    130. nowProess.roundTime = nowProess.finishTime - nowProess.arriveTime;// 计算周转时间
    131. nowProess.aveRoundTime = (double) nowProess.roundTime / nowProess.serveTime;// 计算平均周转时间
    132. new_jcb.add(nowProess);// 经处理过数据后加入new_jcb容器
    133. EnqueueFirst();// 已到达的进程先入队
    134. } else {
    135. EnqueueFirst();// 已到达的进程先入队
    136. link.addLast(nowProess);// 上一轮出的再紧接着进入队尾
    137. }
    138. }
    139. public void DisplayQueue() {// 队列中等候的进程
    140. i++;
    141. System.out.println("第" + i + "次队列中排队的进程:" + link);
    142. }
    143. }
    144. public void printProcess() {
    145. System.out.println("进程名 到达时间 服务时间 开始时间 完成时间 周转时间 带权周转时间");
    146. for (int i = 0; i < new_jcb.size(); ++i) {
    147. System.out.println("P" + new_jcb.get(i).name + " " + new_jcb.get(i).arriveTime + " " +
    148. new_jcb.get(i).serveTime + " " + new_jcb.get(i).beginTime + " " + new_jcb.get(i).finishTime +
    149. " " + new_jcb.get(i).roundTime + " " + new_jcb.get(i).aveRoundTime);
    150. }
    151. new_jcb.clear();// 清空new_jcb容器内的内容,方便存储各种算法的结果并展示
    152. }
    153. }
    154. class compareSt implements Comparator {// 按服务时间升序
    155. public int compare(JCB arg0, JCB arg1) {
    156. return arg0.serveTime - arg1.serveTime;
    157. }
    158. }
    159. class compareAt_St implements Comparator {// 按到达时间升序,若到达时间相同,按服务时间升序
    160. public int compare(JCB o1, JCB o2) {
    161. int a = o1.arriveTime - o2.arriveTime;
    162. if (a > 0)
    163. return 1;
    164. else if (a == 0) {
    165. return o1.serveTime > o2.serveTime ? 1 : -1;
    166. } else
    167. return -1;
    168. }
    169. }
    170. class comparePriority implements Comparator {// 按响应比升序排序
    171. public int compare(JCB o1, JCB o2) {
    172. double r1 = (double) o1.waitTime / o1.serveTime;
    173. double r2 = (double) o2.waitTime / o2.serveTime;
    174. return r1 > r2 ? 1 : -1;
    175. }
    176. }
    177. public class TestProcess {
    178. public static void main(String[] args) {
    179. processMenu pm = new processMenu();
    180. pm.init();// 初始化容器
    181. System.out.println("请输入您想看到的进程调度结果序号即可:\n" +
    182. "输入1:先来先服务调度算法\n" +
    183. "输入2:短作业优先调度算法\n" +
    184. "输入3:最高响应比调度算法\n" +
    185. "输入0:结束进程");
    186. Scanner in=new Scanner(System.in);
    187. int data=in.nextInt();
    188. switch (data) {
    189. case 1:
    190. pm.FCFS();
    191. pm.printProcess();
    192. break;
    193. case 2:
    194. pm.SJF();
    195. pm.printProcess();
    196. break;
    197. case 3:
    198. pm.HRRN();
    199. pm.printProcess();
    200. break;
    201. case 0:
    202. System.exit(0);
    203. break;
    204. }
    205. }
    206. }

  • 相关阅读:
    关于数据中心的设计方案,数据中心网络规划设计
    GDB调试多线程代码
    ASP.NET 6启动时自动创建MongoDB索引
    CURL命令 : GET、POST请求、文件下载等常用命令
    用Abp实现双因素认证(Two-Factor Authentication, 2FA)登录(一):认证模块
    内置第三方apk总结
    基于android的车辆违章停放执法移动APP(ssm+uinapp+Mysql)-计算机毕业设计
    前端如何优化工程
    JavaScript 65 JavaScript 类 65.2 JavaScript 类继承
    与 Dave 和 Ruba 一起探讨亚马逊云科技 2023 芯片创新日
  • 原文地址:https://blog.csdn.net/Protinx/article/details/128107110