don't click here

Java concurrency help

Discussion in 'Technical Discussion' started by Travelsonic, Apr 29, 2017.

  1. Travelsonic

    Travelsonic

    Member
    827
    20
    18
    So I am retaking my Operating Systems class, and this time around, we're working with Java.

    Same project as last semester (simulate putting processes on a pending list, moving them, when the time is right, to the ready list, run them, and when they run to completion, move them to a finished list), different language.

    This time around, I am having trouble with the concurrency part. Mainly, getting it so I can run the threads that check whether there are pending processes (and if those processes can be moved to the ready list), runs the process, checks whether or not the process has completed, or has run out of time on the CPU/needs to be moved back to the ready list, THEN runs something to increment the clock, which (based on the impression I got from my prof) needed to be done separately. My clock is an AtomicInteger... oh hell, let me just post the mess that I already have.

    Just feels like things are not running quite right - I am part of the way there, or a big part of the way there, rather, but am missing something to make it work right/need to figure out not just what that is, but how to fix it. Another issue in my code that I need help fixing is if a running process runs out of time, and needs to be moved back to the ready list... that seems to get me stuck in an infinite loop, and I am having trouble debugging the problem (derping hard).

    Yes, I am aware that there are probably a shitton of issues, and most likely I have also neglected to be fully aware of issues regarding threads trying to modify data at the same time, which is why I am asking for help.

    Just a note: In the code, I put a few PCBs on the pending list. This is just for testing purposes, I have a file containing data that the prof. gave us, which I will use to create PCBs/push them onto the waiting list, but I want to make sure all these core components work BEFORE doing that.

    Code (Text):
    1.  
    2. import java.util.ArrayList;
    3. import java.util.Collections;
    4. import java.util.Iterator;
    5. import java.util.List;
    6. import java.util.concurrent.ExecutorService;
    7. import java.util.concurrent.Executors;
    8. import java.util.concurrent.atomic.AtomicInteger;
    9. import java.util.concurrent.locks.ReentrantLock;
    10.  
    11. public class simulation {
    12.     public static void main(String[] args){
    13.         // VARAIBLES:
    14.         // ATOMIC VARIABLES:
    15.         AtomicInteger clock = new AtomicInteger(0);                                     // Our system clock
    16.         // LISTS:
    17.         List<pcb> pendingList = Collections.synchronizedList(new ArrayList<pcb>());     // For processes that have yet to enter the system
    18.         List<pcb> readyList = Collections.synchronizedList(new ArrayList<pcb>());       // For processes that are ready, but need a CPU to be come available
    19.         List<pcb> finishedList = Collections.synchronizedList(new ArrayList<pcb>());    // For processes that have completed running
    20.         pendingList.add(new pcb(30,1,2));
    21.         pendingList.add(new pcb(31,2,1));  
    22.         pendingList.add(new pcb(32,3,1));  
    23.         pendingList.add(new pcb(33,4,1));  
    24.         pendingList.add(new pcb(34,5,1));  
    25.         pendingList.add(new pcb(35,6,1));  
    26.        
    27.         // PROCESSOR:
    28.         processor sysProcessor = new processor(1);
    29.         // THREADS WITH RUNNABLES FOR DATA PROCESSING/SIMULATION
    30.         Thread clockThread = new Thread(new clockMgr(clock));
    31.         Thread pendingCheckerThread = new Thread(new checkPending(pendingList, readyList, clock));
    32.         Thread schedulerThread = new Thread(new scheduler(sysProcessor, readyList));
    33.         Thread runProcessThread = new Thread(new processRunner(sysProcessor, readyList, finishedList));
    34.         // Loop until every list except for the finish list is empty - which would signify all work has completed
    35.         while(!pendingList.isEmpty() || !readyList.isEmpty() || (sysProcessor.getRunningProcess() != null)){
    36.             pendingCheckerThread.run();
    37.             schedulerThread.run();
    38.             runProcessThread.run();
    39.             try {
    40.                 pendingCheckerThread.join();
    41.                 schedulerThread.join();
    42.                 runProcessThread.join();
    43.             }
    44.             catch (InterruptedException e) {
    45.             }
    46.             clockThread.run();
    47.             try {
    48.                 clockThread.join();
    49.             }
    50.             catch (InterruptedException e) {
    51.             }
    52.         }
    53.         System.out.print("Simulation finished.  Final runtime: " + clock.get() + "\n");
    54.         System.exit(0);
    55.     }
    56.    
    57.     public static class pcb {
    58.         // VARIABLES:
    59.         private int processID;          // Process ID
    60.         private int timeEntry;          // Time a process is supposed to enter the ready queue
    61.         private int timeNeeded;         // Amount of time the process needs on the CPU to finish executing
    62.         private int timeExecuting;      // Amount of time the process has been executing on the CPU.  Once this value matches timeNeeded, the process will complete, and be moved to the finished queue.
    63.  
    64.         // CONSTRUCTOR FUNCTIONS:
    65.         // This constructor takes in 3 integers - one for each piece of data in the PCB, sets each variable to that data, except for timeExecuting, which defaults to 0.
    66.         public pcb(final int inPid, final int inTimeEntry, final int inTimeNeededToFinish){
    67.             processID = inPid;         
    68.             timeEntry = inTimeEntry;
    69.             timeNeeded = inTimeNeededToFinish;
    70.             timeExecuting = 0; 
    71.         }
    72.        
    73.         // ACCESSOR FUNCTIONS:
    74.         /* FUNCTION: public int getPID();
    75.          *   Inputs: none
    76.          *  Returns: processID
    77.          */
    78.         public int getPID(){return processID;}
    79.         /* FUNCTION: public String getPIDAsString();
    80.          *   Inputs: none
    81.          *  Returns: processID as a String
    82.          */
    83.         public String getPIDAsString(){return Integer.toString(processID);}
    84.         /* FUNCTION: public int getTimeEntry();
    85.          *   Inputs: none
    86.          *  Returns: timeEntry
    87.          */
    88.         public int getTimeEntry(){return timeEntry;}
    89.         /* FUNCTION: public String getTimeEntryAsString();
    90.          *   Inputs: none
    91.          *  Returns: timeEntry as a String
    92.          */
    93.         public String getTimeEntryAsString(){return Integer.toString(timeEntry);}
    94.         /* FUNCTION: public int getTimeExecuting();
    95.          *   Inputs: none
    96.          *  Returns: timeExecuting
    97.          */
    98.         public int getTimeExecuting(){return timeExecuting;}
    99.         /* FUNCTION: public String getTimeExecutingAsString();
    100.          *   Inputs: none
    101.          *  Returns: timeExecuting as a String
    102.          */
    103.         public String getTimeExecutingAsString(){return Integer.toString(timeExecuting);}
    104.         /* FUNCTION: public int getTimeNeededToFinish();
    105.          *   Inputs: none
    106.          *  Returns: timeNeededToFinish
    107.          */
    108.         public int getTimeNeededToFinish(){return timeNeeded;}
    109.         /* FUNCTION: public String getTimeNeededToFinishAsString();
    110.          *   Inputs: none
    111.          *  Returns: timeNeededToFinish as a String
    112.          */
    113.         public String getTimeNeededAsString(){return Integer.toString(timeNeeded);}
    114.        
    115.         // MUTATOR FUNCTIONS:
    116.         /* FUNCTION: public void setPID(final int inPID)
    117.          *   Inputs: final int inPID
    118.          *  Returns: nothing - sets processID's value to inPID's value
    119.          */
    120.         public void setPID(final int inPID){processID = inPID;}
    121.         /* FUNCTION: public void setPriority(final int inPriority)
    122.          *   Inputs: final int inPriority
    123.          *  Returns: nothing - sets processID's value to inPriority's value
    124.          */
    125.         public void setTimeEntry(final int inTimeEntry){timeEntry = inTimeEntry;}
    126.         /* FUNCTION: public void setTimeExecuting(final int inTimeExecuting)
    127.          *   Inputs: final int inTimeExecuting
    128.          *  Returns: nothing - sets timeExecuting's value to inTimeExecuting's value
    129.          */
    130.         public void setTimeExecuting(final int inTimeExecuting){timeExecuting = inTimeExecuting;}
    131.         /* FUNCTION: public void incrementTimeExecuting()
    132.          *   Inputs: none
    133.          *  Returns: nothing - function just increments timeExecuting's value.
    134.          */
    135.         public void incrementTimeExecuting(){timeExecuting++;}  
    136.         /* FUNCTION: public void setTimeNeededToFinish(final int inTimeNeededToFinish)
    137.          *   Inputs: final int inTimeNeededToFinish
    138.          *  Returns: nothing - sets timeNeededToFinish's value to inTimeNeededToFinish's value
    139.          */
    140.         public void setTimeNeeded(final int inTimeNeededToFinish){timeNeeded = inTimeNeededToFinish;}
    141.     }
    142.  
    143.     public static class processor{
    144.         private int burstTime;
    145.         private pcb runningProcess;
    146.         public processor(final int inBurstTime){
    147.             burstTime = inBurstTime;
    148.             runningProcess = null;
    149.         }
    150.         public pcb getRunningProcess(){return runningProcess;}      // Retrieve the running process' pcb without removing it from the processor
    151.         public pcb removeRunningProcess(){
    152.             pcb pToReturn = runningProcess;
    153.             runningProcess = null;
    154.             return pToReturn;
    155.         }
    156.         public int getBurstTime(){return burstTime;}
    157.         public void setRunningProcess(pcb inRunningProcess){runningProcess = inRunningProcess;}
    158.         public void setBurstTime(final int inBurstTime){burstTime = inBurstTime;}
    159.     }
    160.    
    161.     public static class clockMgr implements Runnable{
    162.         private AtomicInteger sysClock;
    163.         static ReentrantLock clockLock = new ReentrantLock(true);
    164.         public clockMgr(AtomicInteger inClock){
    165.             sysClock = inClock;
    166.         }
    167.         public void run() {
    168.             clockLock.lock();
    169.             try {
    170.                 sysClock.incrementAndGet();
    171.             }
    172.             catch(Exception e) {
    173.             }
    174.             finally{
    175.             clockLock.unlock();
    176.             }
    177.         }
    178.     }
    179.    
    180.     public static class checkPending implements Runnable{
    181.         private AtomicInteger sysClock;
    182.         private List<pcb> pendingList;
    183.         private List<pcb> readyList;
    184.         public checkPending(List<pcb> inPendingList, List<pcb> inReadyList, AtomicInteger inClock){
    185.             sysClock = inClock;
    186.             pendingList = inPendingList;
    187.             readyList = inReadyList;
    188.         }
    189.         public void run(){
    190.             try{
    191.                 if(pendingList.isEmpty()){return;}
    192.                 for(Iterator<pcb> i = pendingList.iterator(); i.hasNext();) {
    193.                     pcb pendingProcess = i.next();
    194.                     if(sysClock.get() == pendingProcess.getTimeEntry()){
    195.                         System.out.print("Moving process PID " + pendingProcess.getPID() + " from the pending list, to the ready list.\n\n");
    196.                         readyList.add(pendingProcess); 
    197.                         pendingList.remove(pendingProcess);
    198.                     }
    199.                 }          
    200.             }
    201.             catch (Exception e) {
    202.             }
    203.         }
    204.     }    
    205.    
    206.     public static class processRunner implements Runnable{
    207.         private processor sysProcessor;
    208.         private List<pcb> readyList;
    209.         private List<pcb> finishedList;
    210.         public processRunner(processor inSysProcessor, List<pcb> inReadyList, List<pcb> inFinishedList){
    211.             sysProcessor = inSysProcessor;
    212.             readyList = inReadyList;
    213.             finishedList = inFinishedList;
    214.         }
    215.         public void run(){
    216.             try{
    217.                 // If the time running is greater or equal to the time needed to run, move the process to the finished queue
    218.                 if((sysProcessor.getRunningProcess().getTimeExecuting() == sysProcessor.getRunningProcess().getTimeNeededToFinish())){
    219.                     System.out.print("Process PID " + sysProcessor.getRunningProcess().getPID() + " has finished executing.  Moving it to the finished list.\n\n");
    220.                     finishedList.add(sysProcessor.removeRunningProcess());
    221.                     sysProcessor.setRunningProcess(null);
    222.                     return;
    223.                 }
    224.                 // If the process runs out of time, it will get put on the back of the ready list
    225.                 else if((sysProcessor.getRunningProcess().getTimeExecuting() != 0) && ((sysProcessor.getRunningProcess().getTimeExecuting() % sysProcessor.getBurstTime()) == 0)){
    226.                     System.out.print("Process PID " + sysProcessor.getRunningProcess().getPID() + " has run out of CPU time, moving it back to the ready list.\n\n");
    227.                     readyList.add((readyList.size() - 1),sysProcessor.removeRunningProcess());
    228.                     return;
    229.                 }
    230.                 sysProcessor.getRunningProcess().incrementTimeExecuting();
    231.             }
    232.             catch (Exception e) {
    233.             }
    234.         }
    235.     }
    236.    
    237.     public static class scheduler implements Runnable{
    238.         private processor sysProcessor = null;
    239.         private List<pcb> readyList;
    240.         public scheduler(processor inSysProcessor, List<pcb> inReadyList){
    241.             sysProcessor = inSysProcessor;
    242.             readyList = inReadyList;
    243.         }
    244.         public void run(){
    245.             if(sysProcessor.getRunningProcess() != null){return;}
    246.             else{
    247.                 // If the processor has no pcb on it currently,
    248.                 // Check to see if the ready list is empty:
    249.                 if(readyList.isEmpty()){return;}
    250.                 // If the list is not empty, take a pcb off the front of it, give it to the processor.
    251.                 sysProcessor.setRunningProcess(readyList.remove(0));  
    252.                 System.out.print("Running process PID " + sysProcessor.getRunningProcess().getPID() + ".\n\n");
    253.             }
    254.         }
    255.     }
    256. }
    257.  
    258.  
    259.