一. Clock 算法介绍

二. 改进型Clock算法介绍

2.1 介绍

2.2 代码实现

  1. package com.wangt.java;
  2. import java.util.*;
  3. /**
  4. * @author 王天赐
  5. * @create 2019-12-11 20:27
  6. */
  7. public class ClockProMain {
  8. /**
  9. * 记录命中数
  10. */
  11. private static int selectPages;
  12. /**
  13. * 存储命中率
  14. */
  15. private static double selectPagesRate;
  16. /**
  17. * 内存大小
  18. */
  19. private final static int MEMORY_SIZE = 5;
  20. /**
  21. * 获取随机进程数
  22. * @return
  23. */
  24. private static List<Integer> getProcessSeq(){
  25. // 随机页号的起始值
  26. int start = 1;
  27. // 随机页号的结束值
  28. int end = 10;
  29. List<Integer> processSeq = new ArrayList<>();
  30. for (int i = 0; i < 10; i++) {
  31. processSeq.add(randomInt(start, end));
  32. }
  33. return processSeq;
  34. }
  35. /**
  36. * 随机生成指定范围的Int类型的数
  37. * @param start 开始值
  38. * @param end 结束值为 end - 1
  39. * @return
  40. */
  41. private static int randomInt(int start , int end){
  42. return (int)((Math.random() * (end - start)) + start);
  43. }
  44. /**
  45. * 打印随机生成的页面信息
  46. * @param processSeq
  47. */
  48. public static void printPageInfo(List<Integer> processSeq){
  49. System.out.println("<==================== [页面信息] ====================>");
  50. for (int i = 0; i < processSeq.size(); i++) {
  51. System.out.println("第" + i +"个页面号为:" + processSeq.get(i));
  52. }
  53. System.out.println("<==================== [页面信息] ====================>");
  54. System.out.println();
  55. }
  56. public static void printPageReplacementCase(List<Integer> memory){
  57. for (int i = 0; i < 5; i++) {
  58. if (memory.size() > i) {
  59. System.out.print(memory.get(i) + " ");
  60. } else {
  61. System.out.print("0 ");
  62. }
  63. }
  64. System.out.println();
  65. }
  66. /**
  67. * 第一轮页面扫描
  68. * @param memory
  69. * @return
  70. */
  71. public static Integer firstRoundScan(Map<Integer,Page> memory){
  72. // 要被淘汰的页号
  73. Integer pageNum = -1;
  74. for (Map.Entry<Integer, Page> kv : memory.entrySet()) {
  75. Page page = kv.getValue();
  76. if(page.getVisit() == 0 && page.getEdit() == 0){
  77. pageNum = kv.getKey();
  78. break;
  79. }
  80. }
  81. return pageNum;
  82. }
  83. /**
  84. * 第二轮页面扫描
  85. * @param memory
  86. * @return
  87. */
  88. public static Integer secondRoundScan(Map<Integer,Page> memory){
  89. // 要被淘汰的页号
  90. Integer pageNum = -1;
  91. for (Map.Entry<Integer, Page> kv : memory.entrySet()) {
  92. Page page = kv.getValue();
  93. // 如果寻找到 访问位为 0, 编辑为 1的页面,则停止扫描
  94. if(page.getVisit() == 0 && page.getEdit() == 1){
  95. pageNum = kv.getKey();
  96. break;
  97. }else{
  98. // 第二遍扫描将访问位置为 0
  99. page.setVisit(0);
  100. }
  101. }
  102. return pageNum;
  103. }
  104. public static void main(String[] args) {
  105. List<Integer> processes = getProcessSeq();
  106. Map<Integer,Page> pages = new HashMap<>();
  107. List<Integer> memory = new ArrayList<>();
  108. // 打印随机生成的页面信息
  109. printPageInfo(processes);
  110. for (Integer process : processes) {
  111. // 判断内存中是否有该页面
  112. if(pages.get(process) == null){
  113. // 如果返回值等于null, 则说明内存中没有该页面
  114. // 此时判断内存是否已满
  115. if(memory.size() < MEMORY_SIZE){
  116. // 如果内存没有满, 则直接添加即可
  117. // 该页面访问位置为 0 , 编辑为设置为 0
  118. memory.add(process);
  119. pages.put(process, new Page(process,1,0));
  120. }else{
  121. // 如果内存已满, 则需要换出页面
  122. // 换出策略 : V 表示访问位, E表示编辑位, 0 表示未访问, 1表示已访问/已编辑
  123. // V:0 ,E:0
  124. // V:0 ,E:1
  125. // V:1 ,E:0
  126. // V:1 ,E:1
  127. // 记录需要移除的页号
  128. Integer removePageNum = -1;
  129. do {
  130. // 第一轮扫描 : 查询 => 访问位=0,编辑位=0 的页面号
  131. if ((removePageNum = firstRoundScan(pages)) == -1) {
  132. // 第二轮扫描 : 查询 => 访问位=0,编辑位 =1的页面, 并且将扫描过的页面的访问位置为0
  133. removePageNum = secondRoundScan(pages);
  134. }else {
  135. break;
  136. }
  137. // 第三轮扫描 : 重复上述过程
  138. // 提示 如果都是 访问位=1,编辑位=0, 在进行第二轮扫描后, 都会变成 0,0 !
  139. }while (removePageNum == -1);
  140. // 移除需要淘汰的进程号
  141. memory.remove(removePageNum);
  142. pages.remove(removePageNum);
  143. // 将置换的页面添加进主存中
  144. memory.add(process);
  145. pages.put(process, new Page(process,1,0));
  146. }
  147. }else{
  148. // 命中数加一
  149. selectPages++;
  150. }
  151. // 打印页面置换情况
  152. printPageReplacementCase(memory);
  153. }
  154. }
  155. }
  156. class Page{
  157. // 页号
  158. private Integer pageNumber;
  159. // 访问位
  160. private Integer visit;
  161. // 修改位
  162. private Integer edit;
  163. public Page() {
  164. }
  165. public Page(Integer pageNumber, Integer visit, Integer edit) {
  166. this.pageNumber = pageNumber;
  167. this.visit = visit;
  168. this.edit = edit;
  169. }
  170. public Integer getPageNumber() {
  171. return pageNumber;
  172. }
  173. public void setPageNumber(Integer pageNumber) {
  174. this.pageNumber = pageNumber;
  175. }
  176. public Integer getVisit() {
  177. return visit;
  178. }
  179. public void setVisit(Integer visit) {
  180. this.visit = visit;
  181. }
  182. public Integer getEdit() {
  183. return edit;
  184. }
  185. public void setEdit(Integer edit) {
  186. this.edit = edit;
  187. }
  188. }