/ / Kürzeste verbleibende Zeit zuerst: Java Multithreading - Java, Multithreading, CPU, Scheduling, Simulation

Kürzeste verbleibende Zeit zuerst: Java Multithreading - Java, Multithreading, CPU, Scheduling, Simulation

Ich versuche, CPU-Scheduling-Algorithmen zu simulierenin Java und verwende Multithreading. Ich habe erfolgreich FCFS (First Come First Serve) und SJF (Shortest Job First) implementiert. Aber das Problem ist, wenn ich anfange, an SRTF (Shortest Remaining Time First) zu denken, eine präventive Form von SJF. Ich benutze das folgende Modell:

  • Ein Thread für die CPU, der eine hat CLOCK Variable, die jedes Mal ein Häkchen setzt (ein einfaches Taktinkrement) 100ms. Ich habe ein boolean isAvailable; Flag, mit dem die Prozesse prüfen, ob die CPU verfügbar ist, bevor die Ausführung gestartet wird.
  • Ein Thread für Long Term Scheduler (LTS), der den Prozess von der Prozessliste in eine Ready Queue pusht.
  • Ein Thread für den Short Term Scheduler (STS), der einen Prozess aus der ReadyQueue entnimmt und der CPU zuordnet.
  • Sobald ein Prozess von STS zur Ausführung aus der ReadyQueue entfernt wurde, sucht der Prozess nach dem isAvailable Flagge der CPU. Wenn true, setzt es das Flag auf false und startet seine Ausführung (für die ich nur den Thread zum Schlafen bringe) (100 * burstTime) ms da dies nur eine Simulation ist). Andernfalls bleibt der Prozess nur beschäftigt und wartet: while(CPU.isAvailable != true);.

Ich habe die Liste der Prozesse zusammen mit ihrenankunft und platzzeiten vor hand. Es ist in Ordnung, bis ich non-preemptive Scheduling (FCFS und SJF) simuliere. Aber als ich für SRTF versuche, bin ich nicht in der Lage, einen Weg zu finden, um den aktuell laufenden Prozessthread zu verhindern.

Für SRTF kenne ich den Weg in die Zukunft, um den nächsten Prozess von ReadyQueue auszuwählen. Ich kann versuchen das einzustellen isAvailable Flagge zu false einmal wähle ich einen Prozess aus der Warteschlange, aber dannWoher soll ich wissen, welcher Thread ursprünglich ausgeführt wurde? Und da ich nicht viel Synchronisations-S / W-Threads verwende, werde ich mehrere Prozesse verwenden CPU Faden. Es wird ein bisschen durcheinander. Bitte helfen Sie. Vielen Dank!

Dies ist der Code für einen Prozess:

enum State {ARRIVED, WAITING, READY, RUNNING, EXECUTED}
public class Process implements Runnable
{
int pid;
int arrTime;
int burstTime;
int priority;
long startTime;
long endTime;
State procState = null;

Process(int pid, int arrTime, int burstTime, int priority)
{
this.pid = pid;
this.arrTime = arrTime;
this.burstTime = burstTime;
this.priority = priority;
this.procState = State.ARRIVED;
this.startTime = 0;


this.endTime = 0;    /* I also considered adding a timeElapsedUnderExecution
attribute to the process. So I can check after every cycle if the CPU is still available
and keep incrementing the time elapsed. Once the timeElapsed becomes same as burstTime, i
stop the process. Or if after a cycle, the CPU is not available, i know from where to
resume my Process. Is this the way to go ? */

}

boolean isReady()
{
if((this.arrTime <= CPU.CLOCK) && (this.procState == State.ARRIVED))
return true;
else return false;
}

@Override
public void run() {
// TODO Auto-generated method stub
if(this.procState == State.READY)
this.procState = State.WAITING;

while(!CPU.isAvailable());

try
{
this.procState = State.RUNNING;
System.out.println("Process " + pid + " executing...");
this.startTime = CPU.CLOCK;
System.out.println("Process " + this.pid + ": Begins at " + this.startTime);
Thread.sleep(this.burstTime * 100);
this.endTime = CPU.CLOCK;
System.out.println("Process " + this.pid + ": Ends at " + this.endTime);
this.procState = State.EXECUTED;

}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
System.out.println("Interrupted: " + pid);
e.printStackTrace();
}
}
}

Der Code für die CPU:

    import java.util.LinkedList;
import java.util.Queue;

public class CPU implements Runnable

{
static Long CLOCK = new Long(0);
static LinkedList<Process> ReadyQ = new LinkedList<Process>();
private static boolean isAvailable = true;
static boolean done = false;

public static boolean isAvailable() {
return isAvailable;
}

public static void setAvailable(boolean isAvailable) {
CPU.isAvailable = isAvailable;
}

static void incrementCLOCK()
{
LTS.checkArrival();
CPU.CLOCK++;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Clock Tick: " + CPU.CLOCK);
}

@Override
public void run() {
// TODO Auto-generated method stub
System.out.println("CPU starts.!!!");
while(CPU.done != true)
synchronized(CPU.CLOCK)
{
incrementCLOCK();
}
}
}

Der Code für LTS:

public class LTS implements Runnable
{
private static Process[] pList = null;
private final int NUM;
static Integer procStarted;
static Integer procFinished;
static boolean STSDone = false;


LTS(Process[] pList, int num)
{
this.NUM = num;
LTS.pList = pList;
}

static void checkArrival()
{
if(pList == null) return;
for(int i = 0; i < pList.length; i++)
if(pList[i].isReady())
{
pList[i].procState = State.READY;
System.out.println("Process " + pList[i].pid + " is now ready.");
CPU.ReadyQ.add(pList[i]);
}
}

@Override
public void run() {
// TODO Auto-generated method stub
System.out.println("Long Term Scheduler starts.!!!");
while(LTS.STSDone != true)
{
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println(LTS.STSDone);
System.out.println("LTS ends.!!!");
CPU.done = true;
}
}

Antworten:

0 für die Antwort № 1

Problem Nummer 1 ist, dass Ihr freigegebener Status nicht threadsicher ist. Selbst einfache Dinge wie Boolesche Werte benötigen korrekte Threading-Primitive, um die Sichtbarkeit über Threads hinweg zu gewährleisten (auch als "flüchtig" bezeichnet).