Getting Started
// start changes put your changes here // end changes
Section 6.7.3 provides sample code for implementing a round-robin scheduler for Java threads. Using this code as a starting point, implement a MLFQ scheduler that has two queues. The priorities of threads in the two queues should be 2 and 3 respectively. Have the scheduler select a thread from the highest-priority non-empty queue, set that thread's priority to 5 and allow the thread to run for the time slice for that queue. Assume that times slice for each priority level is 2*DEFAULT_TIME_SLICE and DEFAULT_TIME_SLICE, respectively. When this time slice expires, select the next highest priority thread and repeat the process. Assume that round-robin scheduling is used at each priority level, and that a higher priority thread that wakes up does not preempt a currently executing thread. Unlike multi-level feedback queue scheduling, assume that your simple scheduler does not move threads from one priority-level to another.
Test your scheduler with three threads, one at priority level 3 and two at priority level 2. Have each thread run in a loop incrementing a counter. After every 10,000 loops, have each thread print out its id and the current value of its counter and then sleep for 5 seconds, allowing the next thread to run.
It is important to understand that the JVM has its own thread
scheduler that uses priorities. Your scheduler does not replace the
JVM scheduler, rather it emulates a (user-level) scheduling policy
using the notion of priorities. By increasing the priority of the next
thread to be scheduled, your user-level sheduler helps the JVM
scheduler "pick" the right thread for execution. In some sense, the
JVM scheduler acts like a kernel CPU scheduler that we learnt in
class, while your scheduler acts like a user-level scheduler in a
threads library.
A data object is to be shared among several concurrent threads
Some of the threads - Readers want only to read the content of the shared
object. When a reader, reads the content of the shared object (an integer
variable), it should produce the following output to the screen:
Reader <id> reading <integer>where <id> is the unique identifier of the Reader and <integer> is the current value of the shared integer variable.
The Writer threads want to update (i.e. to read and write) the shared object. When a writer updates the shared object (by incrementing it by 1), it should produce the following output on the screen:
Writer <id> writing <integer>where <id> is the unique identifier of the writer and <integer> is the new value written to the shared object.
Test your solution with multiple readers and writers. Of course, with multiple readers and writers, the output will illustrate the concurrency provided by threads.
Your code should prompt for the number of readers and the number of writers, in that order. You can assume that a valid integer is provided by the user for each of these. You should be sure that your code works for different inputs as we may test it with inputs other than what you provide in your sample output listing.
10 percent of your lab grade will come from your participation in this project as a member of your two person group.
What you need to turn in (each person individually):
Turn in a hard copy of your assessment of the division of labor in the group in the format shown below. If you give yourself a 50% and your partner gives you a 50%, you will get the whole 10 points. If you give your partner a 40% and your partner gives himself or herself a 40%, he or she will get 8 points. And so on...