最短剩余时间优先(Shortest Remaining Time First):Java 多线程

7
我正在尝试在Java中模拟CPU调度算法,并使用多线程。我已经成功实现了FCFS(先进先出)和SJF(最短作业优先)算法。但是问题在于,当我开始思考SRTF(剩余时间最短优先)时,这是SJF的一种抢占式形式。
我使用以下模型: - 一个CPU线程,具有一个CLOCK变量,每100ms递增一次。我有一个布尔型isAvailable;标志用于进程在开始执行之前检查CPU是否可用。 - 长期调度器(LTS)线程,将进程从进程列表推入Ready Queue。 - 短期调度器(STS)线程,从ReadyQueue中取出一个进程并分配给CPU。 - 一旦STS从ReadyQueue中删除进程以进行执行,该进程会检查CPU的isAvailable标志。如果为true,则设置标志为false并开始执行(仅使线程睡眠(100 * burstTime)ms,因为这只是一种模拟)。否则,进程将保持忙等待:while(CPU.isAvailable!= true);
我预先有进程列表及其到达时间和运行时间。在模拟非抢占式调度(FCFS和SJF)时还好。但是,当我尝试使用SRTF时,我无法找到抢占当前正在运行的进程线程的方法。
对于SRTF,我知道如何从准备队列中选择下一个进程。我可以尝试在从队列中选择进程之后将isAvailable标志设置为false,但是如何知道最初正在执行哪个线程呢?由于我没有在线程之间使用太多同步,所以我会有多个进程使用CPU线程。这变得有点混乱。请帮忙,谢谢!
以下是一个Process的代码:
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();
    }
    }
}

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();
            }
    }
}

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;
    }
}

需要展示更多的代码,具体地说是CPU相关的代码。 - jtahlborn
我已经添加了“CPU”和“LTS”的代码。 - akaHuman
while(!CPU.isAvailable());while (CPU.done!=true) 和相关的条件循环与非易失性布尔值 + 编译器优化 = 令人头痛 -- 这是2012年的东西,它怎么上了第一页 - aran
1个回答

0

问题1是你的共享状态不是线程安全的。即使是像布尔值这样的简单东西,也需要正确的线程原语来确保在线程之间的可见性(也称为“volatile”)。


请问您能详细说明一下吗?谢谢! - akaHuman
3
这个主题太大了,在这里无法详细阐述。许多人推荐阅读这本书:http://www.amazon.com/Java-Concurrency-Practice-Brian-Goetz/dp/0321349601 - Esko Luontola

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接