一. Clock 算法介绍
二. 改进型Clock算法介绍
2.1 介绍
2.2 代码实现
package com.wangt.java;
import java.util.*;
/**
* @author 王天赐
* @create 2019-12-11 20:27
*/
public class ClockProMain {
/**
* 记录命中数
*/
private static int selectPages;
/**
* 存储命中率
*/
private static double selectPagesRate;
/**
* 内存大小
*/
private final static int MEMORY_SIZE = 5;
/**
* 获取随机进程数
* @return
*/
private static List<Integer> getProcessSeq(){
// 随机页号的起始值
int start = 1;
// 随机页号的结束值
int end = 10;
List<Integer> processSeq = new ArrayList<>();
for (int i = 0; i < 10; i++) {
processSeq.add(randomInt(start, end));
}
return processSeq;
}
/**
* 随机生成指定范围的Int类型的数
* @param start 开始值
* @param end 结束值为 end - 1
* @return
*/
private static int randomInt(int start , int end){
return (int)((Math.random() * (end - start)) + start);
}
/**
* 打印随机生成的页面信息
* @param processSeq
*/
public static void printPageInfo(List<Integer> processSeq){
System.out.println("<==================== [页面信息] ====================>");
for (int i = 0; i < processSeq.size(); i++) {
System.out.println("第" + i +"个页面号为:" + processSeq.get(i));
}
System.out.println("<==================== [页面信息] ====================>");
System.out.println();
}
public static void printPageReplacementCase(List<Integer> memory){
for (int i = 0; i < 5; i++) {
if (memory.size() > i) {
System.out.print(memory.get(i) + " ");
} else {
System.out.print("0 ");
}
}
System.out.println();
}
/**
* 第一轮页面扫描
* @param memory
* @return
*/
public static Integer firstRoundScan(Map<Integer,Page> memory){
// 要被淘汰的页号
Integer pageNum = -1;
for (Map.Entry<Integer, Page> kv : memory.entrySet()) {
Page page = kv.getValue();
if(page.getVisit() == 0 && page.getEdit() == 0){
pageNum = kv.getKey();
break;
}
}
return pageNum;
}
/**
* 第二轮页面扫描
* @param memory
* @return
*/
public static Integer secondRoundScan(Map<Integer,Page> memory){
// 要被淘汰的页号
Integer pageNum = -1;
for (Map.Entry<Integer, Page> kv : memory.entrySet()) {
Page page = kv.getValue();
// 如果寻找到 访问位为 0, 编辑为 1的页面,则停止扫描
if(page.getVisit() == 0 && page.getEdit() == 1){
pageNum = kv.getKey();
break;
}else{
// 第二遍扫描将访问位置为 0
page.setVisit(0);
}
}
return pageNum;
}
public static void main(String[] args) {
List<Integer> processes = getProcessSeq();
Map<Integer,Page> pages = new HashMap<>();
List<Integer> memory = new ArrayList<>();
// 打印随机生成的页面信息
printPageInfo(processes);
for (Integer process : processes) {
// 判断内存中是否有该页面
if(pages.get(process) == null){
// 如果返回值等于null, 则说明内存中没有该页面
// 此时判断内存是否已满
if(memory.size() < MEMORY_SIZE){
// 如果内存没有满, 则直接添加即可
// 该页面访问位置为 0 , 编辑为设置为 0
memory.add(process);
pages.put(process, new Page(process,1,0));
}else{
// 如果内存已满, 则需要换出页面
// 换出策略 : V 表示访问位, E表示编辑位, 0 表示未访问, 1表示已访问/已编辑
// V:0 ,E:0
// V:0 ,E:1
// V:1 ,E:0
// V:1 ,E:1
// 记录需要移除的页号
Integer removePageNum = -1;
do {
// 第一轮扫描 : 查询 => 访问位=0,编辑位=0 的页面号
if ((removePageNum = firstRoundScan(pages)) == -1) {
// 第二轮扫描 : 查询 => 访问位=0,编辑位 =1的页面, 并且将扫描过的页面的访问位置为0
removePageNum = secondRoundScan(pages);
}else {
break;
}
// 第三轮扫描 : 重复上述过程
// 提示 如果都是 访问位=1,编辑位=0, 在进行第二轮扫描后, 都会变成 0,0 !
}while (removePageNum == -1);
// 移除需要淘汰的进程号
memory.remove(removePageNum);
pages.remove(removePageNum);
// 将置换的页面添加进主存中
memory.add(process);
pages.put(process, new Page(process,1,0));
}
}else{
// 命中数加一
selectPages++;
}
// 打印页面置换情况
printPageReplacementCase(memory);
}
}
}
class Page{
// 页号
private Integer pageNumber;
// 访问位
private Integer visit;
// 修改位
private Integer edit;
public Page() {
}
public Page(Integer pageNumber, Integer visit, Integer edit) {
this.pageNumber = pageNumber;
this.visit = visit;
this.edit = edit;
}
public Integer getPageNumber() {
return pageNumber;
}
public void setPageNumber(Integer pageNumber) {
this.pageNumber = pageNumber;
}
public Integer getVisit() {
return visit;
}
public void setVisit(Integer visit) {
this.visit = visit;
}
public Integer getEdit() {
return edit;
}
public void setEdit(Integer edit) {
this.edit = edit;
}
}