import java.util.LinkedList;
import java.util.Random;
public class Main {
public static void main(String[] args) throws InterruptedException {
new ProcessMemoryScheduling().run();
}
}
public class PCB {
String name;
int needMemory;
int address;
double arriveTime;
double needTime;
double hasUsedTime;
String status;
}
public class MemoryBlock {
int address;
int length;
String status = "Free";
MemoryBlock(int address, int length) {
this.address = address;
this.length = length;
}
}
public class ProcessMemoryScheduling {
private static int PROCESS_NUM = 10;
private int blocked = 0;
private int blockIndex = -1;
private PCB[] pcb = new PCB[PROCESS_NUM];
private LinkedList<MemoryBlock> memoryBlockList = new LinkedList<>();
private double timeSlice;
private int runningIndex;
private long lastTime;
private long beginTime;
private boolean isFinishALLProcess() {
for (int i = 0; i < PROCESS_NUM; i++) {
if (!pcb[i].status.equals("Finish")) {
return false;
}
}
return true;
}
private void initData() {
runningIndex = -1;
Random r = new Random();
for (int n = 0; n < PROCESS_NUM; n++) {
pcb[n] = new PCB();
pcb[n].name = "P" + Integer.toString(n + 1);
pcb[n].needTime = r.nextDouble() * 4 + 12;
pcb[n].needMemory = r.nextInt(122) + 38;
if (n == 0) {
pcb[n].arriveTime = 0;
pcb[0].needMemory = 50;
} else {
pcb[n].arriveTime = r.nextDouble() * 5 + 1;
pcb[n].needMemory = r.nextInt(122) + 38;
}
}
for (int n = 0; n < PROCESS_NUM; n++) {
pcb[n].hasUsedTime = 0;
pcb[n].address = 0;
pcb[n].status = "U";
}
MemoryBlock firstBlock = new MemoryBlock(0, 1024);
memoryBlockList.add(firstBlock);
print();
}
private String d2s(double d) {
String tmp = d + "";
int index = tmp.indexOf(".");
int EXACT_DIGIT = 1;
return tmp.substring(0, index + EXACT_DIGIT + 1);
}
private int getStandard(int i, int j) {
PCB key = pcb[i];
while (i < j) {
while (i < j && pcb[j].arriveTime >= key.arriveTime) {
j--;
}
if (i < j) {
pcb[i] = pcb[j];
}
while (i < j && pcb[i].arriveTime <= key.arriveTime) {
i++;
}
if (i < j) {
pcb[j] = pcb[i];
}
}
pcb[i] = key;
return i;
}
private void quickSortByArriTime(int low, int high) {
if (low < high) {
int standard = getStandard( low, high);
quickSortByArriTime( low, standard - 1);
quickSortByArriTime(standard + 1, high);
}
}
private void print() {
System.out.println("\n-----------------------------------------------------------------------------");
System.out.println("内存分区表(Busy:占用 Free:空闲):");
System.out.println("起址(K) 长度(KB) 状态");
for (MemoryBlock memoryBlock : memoryBlockList) {
System.out.printf("%-8d %-10d %-6s\n", memoryBlock.address, memoryBlock.length, memoryBlock.status);
}
System.out.println("\n后备队列中的作业:");
for (int i = 0; i < PROCESS_NUM; i++) {
if (pcb[i].status.equals("U")) {
System.out.print(pcb[i].name + "\t");
}
}
System.out.println("\n当前各进程PCB信息:");
System.out.print("进程名 到达时间/s 需要时间/s 已用时间/s 所需内存/KB 内存起址 进程状态\n");
for (int i = 0; i < PROCESS_NUM; i++) {
if (!pcb[i].status.equals("U")) {
System.out.printf("%-6s %-10s %-10s %-10s %-11d %-8d %-8s\n", pcb[i].name, d2s(pcb[i].arriveTime)
, d2s(pcb[i].needTime), d2s(pcb[i].hasUsedTime), pcb[i].needMemory, pcb[i].address, pcb[i].status);
}
}
System.out.println("-----------------------------------------------------------------------------");
lastTime = System.currentTimeMillis();
}
private int getNextWaiting(int curr) {
int p = curr;
while ((p = ++p % PROCESS_NUM) != curr) {
if (pcb[p].status.equals( "Waiting") ) {
return p;
}
}
return -1;
}
private void getNextOnDisk(double allTime) {
int memoryProcessNum = 0;
for (PCB aPcb : pcb) {
if (aPcb.status.equals("Waiting") || aPcb.status.equals("Running") || aPcb.status.equals("Blocking")) {
memoryProcessNum++;
}
}
int MAX_OCCURS = 5;
if (memoryProcessNum < MAX_OCCURS) {
for (int p = 0; p < pcb.length && memoryProcessNum < MAX_OCCURS; p++) {
if (pcb[p].status.equals("U") && allTime >= pcb[p].arriveTime) {
int address = applyMemory(p);
if (address != -2) {
pcb[p].address = address;
pcb[p].status = "Waiting";
memoryProcessNum++;
}
}
}
}
}
private int applyMemory(int curr) {
if (!pcb[curr].status.equals("U")) {
return -2;
}
MemoryBlock target = null;
int needMemory = pcb[curr].needMemory;
for (MemoryBlock memoryBlock : memoryBlockList) {
if (memoryBlock.status.equals("Free") && memoryBlock.length >= needMemory) {
target = memoryBlock;
break;
}
}
if (target == null) {
return -2;
} else if (target.length == needMemory) {
target.status = "Busy";
return target.address;
} else {
target.status = "Busy";
MemoryBlock block = new MemoryBlock(target.address + needMemory, target.length - needMemory);
target.length -= block.length;
memoryBlockList.add(memoryBlockList.indexOf(target) + 1, block);
return target.address;
}
}
private void releaseMemory(int address) {
MemoryBlock target = null;
for (MemoryBlock memoryBlock : memoryBlockList) {
if (memoryBlock.address == address) {
target = memoryBlock;
break;
}
}
if (target == null){
return;
}
if(memoryBlockList.size()==1){
target.status = "Free";
return;
}
int index = memoryBlockList.indexOf(target);
if (index == 0) {
MemoryBlock memoryBlock = memoryBlockList.get(1);
if (memoryBlock.status.equals( "Free")) {
target.length += memoryBlock.length;
memoryBlockList.remove(memoryBlock);
}
target.status = "Free";
} else if (index == memoryBlockList.size() - 1) {
MemoryBlock m = memoryBlockList.get(index - 1);
if (m.status.equals("Free") ) {
m.length += target.length;
memoryBlockList.remove(target);
}
target.status = "Free";
} else {
MemoryBlock preMemoryBlock= memoryBlockList.get(index - 1);
MemoryBlock nextMemoryBlock = memoryBlockList.get(index + 1);
if (preMemoryBlock.status.equals("Free") && nextMemoryBlock.status.equals( "Free")) {
preMemoryBlock.length += target.length;
preMemoryBlock.length += nextMemoryBlock.length;
memoryBlockList.remove(target);
memoryBlockList.remove(nextMemoryBlock);
} else if (preMemoryBlock.status.equals("Free") && nextMemoryBlock.status.equals("Busy") ) {
preMemoryBlock.length += target.length;
memoryBlockList.remove(target);
} else if (preMemoryBlock.status.equals("Busy") && nextMemoryBlock.status.equals("Free") ) {
target.length += nextMemoryBlock.length;
target.status = "Free";
memoryBlockList.remove(nextMemoryBlock);
} else {
target.status = "Free";
}
}
}
private void dispatch() throws InterruptedException {
if (isFinishALLProcess()) {
return;
}
long now = System.currentTimeMillis();
double passedTime = (now - lastTime) / 1000.0;
double allTime = (now - beginTime) / 1000.0;
getNextOnDisk(allTime);
if (runningIndex != -1) {
double oldhasUsedTime = pcb[runningIndex].hasUsedTime;
if (passedTime >= timeSlice) {
if (oldhasUsedTime + passedTime >= pcb[runningIndex].needTime) {
pcb[runningIndex].hasUsedTime = pcb[runningIndex].needTime;
pcb[runningIndex].status = "Finish";
releaseMemory(pcb[runningIndex].address);
} else {
pcb[runningIndex].hasUsedTime = oldhasUsedTime + timeSlice;
pcb[runningIndex].status = "Waiting";
}
int next = getNextWaiting(runningIndex);
if (next != -1) {
pcb[next].status = "Running";
runningIndex = next;
print();
}
}
} else {
pcb[0].status = "Running";
runningIndex = 0;
print();
}
Random random = new Random();
int randomNum = random.nextInt(3);
if (randomNum == 2 && (blocked == 0 ) ) {
blockIndex = runningIndex;
pcb[runningIndex].status = "Blocking";
blocked = 1;
runningIndex = getNextWaiting(runningIndex);
}
if (blocked == 1) {
long time = System.currentTimeMillis();
double intervalTime = (time - lastTime) / 1000.0;
if (runningIndex == -1) {
Thread.sleep(1000);
runningIndex = blockIndex;
pcb[runningIndex].status = "Waiting";
blocked = 0;
} else if (intervalTime > 2.0) {
if (blockIndex != -1) {
pcb[blockIndex].status = "Waiting";
blocked = 0;
}
}
}
}
public void run() throws InterruptedException {
System.out.println();
System.out.println("------------------------------------------------------");
System.out.println(" 课程设计:进程管理系统 ");
System.out.println("------------------------------------------------------");
initData();
timeSlice=2;
quickSortByArriTime(0, PROCESS_NUM - 1);
beginTime = System.currentTimeMillis();
lastTime = System.currentTimeMillis();
while (true) {
dispatch();
if (isFinishALLProcess()) {
break;
}
}
print();
System.out.print("------------------所有进程运行结束------------------\n\n");
}
}