nachos-java Task1.3 Alarm

来源:互联网 发布:mac怎么关闭开机声音 编辑:程序博客网 时间:2024/06/09 18:01

Task 1.3 Alarm

  • 实验要求
  • 实验关键代码
  • 试验测试代码
  • 关键代码分析
  • 测试结果分析

实验要求

◆ Complete the implementation of the Alarm class, by implementing the waitUntil(long x) method.

◆ A thread calls waitUntil to suspend its own execution until time has advanced to at least now + x.

◆ This is useful for threads that operate in real-time, for example, for blinking the cursor once per second.

◆ There is no requirement that threads start running immediately after waking up; just put them on the ready queue in the timer interrupt handler after they have waited for at least the right amount of time.

◆ Do not fork any additional threads to implement waitUntil();

◆ you need only modify waitUntil() and the timer interrupt handler.

◆ waitUntil is not limited to one thread;

◆ any number of threads may call it and be suspended at any one time.

实验关键代码

变量声明

private static LinkedList<WaitForAlarmThread> waitForAlarmThreadList ;

方法实现

关键代码在waitForUntil(long x)方法和timerInterrupt()方法。

1、Void waitUntil(long x)方法:

public void waitUntil(long x) {    // for now, cheat just to get something working (busy waiting is bad)    boolean preState = Machine.interrupt().disable();//关中断    long wakeTime = Machine.timer().getTime()+x;//计算唤醒的时间    WaitForAlarmThread waitForAlarmThread = new WaitForAlarmThread(wakeTime, KThread.currentThread());    waitForAlarmThreadList.add(waitForAlarmThread);//将线程加入到等待链表中    KThread.sleep();//让该线程睡眠    Machine.interrupt().restore(preState);//恢复中断   }

2、WaitForAlarmThread类【包含线程和唤醒时间的数据结构】

class WaitForAlarmThread{    long wakeTime;    KThread thread;    public WaitForAlarmThread(long wakeTime,KThread thread){        this.wakeTime=wakeTime;        this.thread=thread;    }}

3、Void timerInterrupt()方法:

public void timerInterrupt() {    boolean preState = Machine.interrupt().disable();//关中断    WaitForAlarmThread x;    for(java.util.Iterator i = waitForAlarmThreadList.iterator();i.hasNext();){        x = (WaitForAlarmThread)i.next();//取出链表中的每个线程判断是否达到唤醒时间        if(x.wakeTime<=Machine.timer().getTime()){//如果达到唤醒时间,将其从链表中移除并唤醒该线程            i.remove();            x.thread.ready();        }    }    Machine.interrupt().restore(preState);//恢复中断    }

实验测试代码

public static void AlarmTest(){    KThread a = new KThread(new Runnable() {        public void run() {            System.out.println("线程1启动");            for(int i = 0;i<5;i++){                if(i == 2){                    System.out.println("线程1要暂时隐退,此时时间为:"+Machine.timer().getTime()+",大约1700clock ticks之后再见");                    new Alarm().waitUntil(800);                    System.out.println("线程1回来了,此时时间为:"+Machine.timer().getTime());                }                System.out.println("*** thread 1 looped "                           + i + " times");                KThread.currentThread().yield();            }        }    });    a.fork();    for(int i = 0;i<5;i++){            if(i == 2){                System.out.println("线程0要暂时隐退,此时时间为:"+Machine.timer().getTime()+",大约800clock ticks之后再见");                new Alarm().waitUntil(1700);                System.out.println("线程0回来了,此时时间为:"+Machine.timer().getTime());            }        System.out.println("*** thread 0 looped "                   + i + " times");        KThread.currentThread().yield();    }}

关键代码分析

思路分析

要想实现void waitForUntil (long x)方法,要将当前线程保存起来,记录线程唤醒时间,然后在达到唤醒时间时将其唤醒。

新建一个数据结构含有变量KThread线程和唤醒时间【在本实验中为waketime】,每次调用waitForUntil(long x)方法时,会将调用线程包装成新建数据结构的对象,并将其加入等待队列中,当到达唤醒时间时将其唤醒即可。

方法解释

1、Void waitForUntil (long x) 方法

通过参数与当前时间算出唤醒时间,将线程与唤醒时间包装起来,加入waitForAlarmThreadList中,然后让该线程睡眠。

2、void timerInterrupt ( ) 方法

这个方法大约每500 clock ticks执行一次,所以每次检查waitForAlarmThreadList 中的所有线程,如果线程的唤醒时间达到,则将其唤醒。

关键点和难点

关键点:知道如何将待唤醒的线程保存起来,使用数据结构将线程和唤醒时间绑在一起。
难点:理解void timerInterrupt()方法大约每500 clock ticks 执行一次。

测试结果分析

测试结果截图

这里写图片描述

测试结果分析

线程0(在测试代码中为main线程)先执行一次,然后yield;

然后线程1(在测试代码中为a线程)执行一次,如此反复,直到当线程0执行第三次的时候,线程0调用了waitUntil(1700)方法,所以线程0会在大约1700 clock ticks 后继续执行,当线程1执行第三次时,也调用了waitForUntil()方法,参数为800,故线程1会在大约800 clock ticks 之后继续执行,通过看控制台打印结果,可知编写正确。

0 0
原创粉丝点击