Project 2 is similar to project 1. The user creates several simulated processes, then runs them. The difference is that each process will run in real time and will be represented as a special kind of thread called a behavior.
Futuristic operating systems are organized around the concept of an agent. Agents execute behaviors, utilize resources, and send messages to other agents. For our purposes a behavior is a thread that can be safely stopped, paused, and unpaused. (Don't use suspend, stop, and resume, these methods are unsafe and have been deprecated.)
Processes are modeled by process-behaviors. A process behavior is a behavior that repeatedly:
1. uses the CPU for a random number of milliseconds
2. reads from an I/O device for a random number of milliseconds
for a random number of cycles. Here's the I/O device you must use:
class IODevice {
private static int hitCount = 0;
public static void read(String name,
long ms) {
try {
Thread.sleep(ms); // simulate
read time for the device
} catch(InterruptedException ie) {
System.out.println(ie.getMessage());
}
System.out.println(
name + " read " +
++hitCount + " in " + ms + "ms");
}
}
Be careful. Only one process behavior at a time may use the IODevice, but the read method is static and not synchronized. The process behavior doesn't need the CPU to read from the I/O device. The delay models the I/O device transferring data to the process behavior.
Here's the CPU model you should use:
class CPU {
public static void work(String name,
long ms) {
long endTime =
System.currentTimeMillis() + ms;
while(true) {
if (endTime <=
System.currentTimeMillis()) break;
}
System.out.println(name + "
worked " + ms + "ms");
}
}
A scheduler-behavior is a behavior that maintains a priority queue called the schedule. The schedule contains behaviors sorted by priority. The scheduler repeatedly:
1. Removes the next behavior from the schedule
2. Discards the behavior if it has stopped and returns to step 1
3. Unpauses or starts the behavior
4. Waits for the behavior to stop, read, or for its time slice (500 ms) to
elapse, which ever happens first.
5. Pauses the behavior, updates its priority, and puts it back into the schedule.
When the schedule is empty, the scheduler behavior stops. The scheduler uses a preemptive version of the shortest job first algorithm.
Note that scheduler behaviors are behaviors. So some of the behaviors that appear in the schedule may also be scheduler behaviors. In other words, a scheduler behavior is the root of a tree. Parent nodes are scheduler behaviors and leaf nodes are process behaviors. We are employing the Composite Design Pattern:
Users should be provided with commands that allow them to create named behaviors, add behaviors to scheduler behaviors, and to start behaviors running:
-> makesb b1 // makes a scheduler behavior named b1
ok
-> makepb p1 // makes a process behavior named p1
ok
-> makepb p2 // makes a process behavior named p2
ok
-> add b1 p1 // adds p1 to
b1.schedule
ok
-> add b1 p2 // adds p2 to
b1.schedule
ok
-> start b1 // starts b1 running
// output from b1 here
-> pause b1 // pauses b1
ok
-> unpause b1 // resumes b1
// more output from b1 appears here
-> stop b1 // stops b1 we could
ok