Multiple Processes, Multiple Processors, Single Priority Queue - Java Thread-Safe and Concurrency -

50 views Asked by At

Currently I am working on a Java question that is related to Java thread and concurrency. The thread should handles Multiple Processes, Multiple Processors and Single Priority Queue.

It has 5 main functions which are set_number_of_processors, reg, start, schedule, and terminate.

My code works fine with 3 sessions. However, when it has 4 sessions. It shows errors. I need some help in figuring what is the problems with my code.

import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.Condition; //Note that the 'notifyAll' method or similar 
import java.util.ArrayList;
import java.util.LinkedList;


public class OS implements OS_sim_interface {
    int pid = 0;
    int numProcessors;
    int numAvailableProcessors;

    ArrayList<Process> processes = new ArrayList<Process>();    //An ArrayList to store the processes

    ArrayList<Process>[] runningProcesses;
    LinkedList<Process> readyQueue = new LinkedList<Process>();     //A LinkedList to store the waiting processes


    //lock and condition variables
    ReentrantLock lock = new ReentrantLock();
    Condition condition = lock.newCondition();

    OS(){
        //default constructor
    }

    @Override
    public void set_number_of_processors(int nProcessors) {
        if(nProcessors < 1){
            System.out.println("Number of processors must be greater than 1");
        }
        runningProcesses = new ArrayList[nProcessors];
        for (int i = 0; i < nProcessors; i++) {
            runningProcesses[i] = new ArrayList<Process>();
        }
        numAvailableProcessors = nProcessors;
        numProcessors = nProcessors;
    }

    @Override
    public int reg(int priority) {
        if(priority <= 0){
            System.out.println("Please give a valid priority (minimum 1)");
            return -1;
        }else{
            //Create a new process
            Process process = new Process(pid, priority);
            //Add the process to the list of processes
            processes.add(process);
            pid++; //Increment the process ID recorded by OS
            return process.ID;
        }
    }

    @Override
    public void start(int ID) {
        if(ID < 0 || ID >= processes.size()){
            System.out.println("Invalid process ID");
        }else{
            Process currProcess = processes.get(ID);
            int currProcessor = 0;
            for (int i = 0; i < numProcessors; i++) {
                if (runningProcesses[i].isEmpty()) {
                    currProcessor = i;
                    break;
                }
            }
            //Check if there are available processors
            if(numAvailableProcessors > 0){
                lock.lock();
                try{
                    currProcess.run();
                    runningProcesses[currProcessor].add(currProcess);
                    System.out.println(currProcess.name + " is running on Processor-" + currProcessor);
                    numAvailableProcessors--;
                }catch(Exception e){
                    System.out.println("Hi, I'm your exception: " + e);
                }finally {
                    lock.unlock();
                }
            }else {
                lock.lock();
                try{
                    readyQueue.add(currProcess);
                    condition.await();
                    System.out.println(currProcess.name + " is added in readyQueueStart");
                }catch(Exception e){
                    System.out.println("Hi, I'm your exception: " + e);
                }finally {
                    lock.unlock();
                }
            }
        }
    }

    @Override
    public void schedule(int ID) {
        if(ID < 0 || ID >= processes.size()){
            System.out.println("Invalid process ID");
        }else{
            Process currProcess = processes.get(ID);
            int currProcessor = 0;
            for (int i = 0; i < numProcessors; i++) {
                if (runningProcesses[i].contains(currProcess)) {
                    currProcessor = i;
                    break;
                }
                // else do nothing
            }
            if(!readyQueue.isEmpty()){
                lock.lock();
                try{
                    //add the current process to readyQueue
                    readyQueue.add(currProcess);
                    System.out.println(currProcess.name + " is added in readyQueue");
                    runningProcesses[currProcessor].remove(currProcess);
                    //wake up the waiting process
                    condition.signal();

                    lock.unlock();
                    //wait for the process to finish
                    lock.lock();
                    //run next process in readyQueue
                    Process newProcess = readyQueue.poll();
                    newProcess.run();
                    runningProcesses[currProcessor].add(newProcess);
                    System.out.println(newProcess.name + " is scheduled running on Processor-" + currProcessor);
                    //wait for the process to finish
                    condition.await();
                }catch(Exception e){
                    System.out.println("Hi, I'm your exception: " + e);
                }finally {
                    lock.unlock();
                }
                return;
            }else{
                System.out.println(currProcess.name + " is already running on Processor-" + currProcessor);
            }

        }
        
    }

    @Override
    public void terminate(int ID) {
        if(ID < 0 || ID >= processes.size()){
            System.out.println("Invalid process ID");
        }else{
            Process currProcess = processes.get(ID);
            int currProcessor = 0;
            for (int i = 0; i < numProcessors; i++) {
                if (runningProcesses[i].contains(currProcess)) {
                    currProcessor = i;
                    break;
                }
                // else do nothing
            }
            if(readyQueue.isEmpty()){
                System.out.println(currProcess.name + " is terminated");
                return;
            }else{
                lock.lock();
                try{
                    //remove the current process from runningProcesses
                    runningProcesses[currProcessor].remove(currProcess);
                    System.out.println(currProcess.name + " is terminated");
                    //wake up the waiting process
                    condition.signal();
                    //run next process in readyQueue
                    Process newProcess = readyQueue.poll();
                    newProcess.run();
                    runningProcesses[currProcessor].add(newProcess);
                    System.out.println(newProcess.name + " is scheduled running on Processor-" + currProcessor);
                }catch(Exception e){
                    System.out.println("Hi, I'm your exception: " + e);
                }finally {
                    lock.unlock();
                }
            }

        }
        
    }

    class Process extends Thread{
        int ID;
        int priority;
        String name;

        Process(int ID, int priority) {
            this.ID = ID;
            this.priority = priority;
            this.name = "Process-" + ID;
        }
    }
}

Thread Class: Default

class ProcessSimThread2 extends Thread {
        int pid = -1;
        int start_session_length=0;
        OS os;
        ProcessSimThread2(OS os){this.os = os;} //Constructor stores reference to os for use in run()
        
        public void run(){

            os.start(pid); 
            events.add("pid="+pid+", session=0");
            try {Thread.sleep(start_session_length);} catch (InterruptedException e) {e.printStackTrace();}
            
            os.schedule(pid);
            events.add("pid="+pid+", session=1");
            
            os.schedule(pid);
            events.add("pid="+pid+", session=2");
            
            os.terminate(pid); 
            events.add("pid="+pid+", session=3"); //Error occured at this session. It works fine if i commented this out
        };  
    };  

Test Class: Default

public void test(){
        System.out.println("\n\n\n*********** test *************");
        events = new ConcurrentLinkedQueue<String>(); //List of process events
        
        //Instantiate OS simulation for two processors
        OS os =  new OS();  
        os.set_number_of_processors(2);
        int priority1 = 1;
        
        //Create two process simulation threads:

        int pid0 = os.reg(priority1); 
        ProcessSimThread2 p0 = new ProcessSimThread2(os); 
        p0.start_session_length = 250; p0.pid = pid0; //p0 grabs first processor and keeps it for 250ms
        
        int pid1 = os.reg(priority1); 
        ProcessSimThread2 p1 = new ProcessSimThread2(os); 
        p1.start_session_length = 50;  p1.pid = pid1; //p1 grabs 2nd processor and keeps it for 50ms
        
        int pid2 = os.reg(priority1);           
        ProcessSimThread2 p2 = new ProcessSimThread2(os); 
        p2.start_session_length = 0; p2.pid = pid2; //p2 tries to get processor straight away but has to wait for p1 os.schedule call
        
        //Start the treads making sure that p0 will get to its first os.start()
        p0.start();
        sleep(20);
        p1.start();
        sleep(25); //make sure that p1 has grabbed a processor before starting p2
        p2.start();

        //Give time for all the process threads to complete:
        sleep(test_timeout);

        String[] expected = { "pid=0, session=0", "pid=1, session=0", "pid=2, session=0", "pid=1, session=1", "pid=2, session=1", "pid=1, session=2", "pid=2, session=2","pid=1, session=3", "pid=2, session=3", "pid=0, session=1", "pid=0, session=2", "pid=0, session=3"};
        
        System.out.println("\nUR4 - NOW CHECKING");
        //Check expected events against actual:
        String test_status = "UR4 PASSED";
        if (events.size() == expected.length) {
             Iterator <String> iterator = events.iterator(); 
             int index=0;
             while (iterator.hasNext()) {
                 String event = iterator.next();
                 if (event.equals(expected[index])) System.out.println("Expected event = "+ expected[index] + ", actual event = " + event + " --- MATCH");
                 else {
                     test_status = "UR3 FAILED - NO MARKS"; 
                     System.out.println("Expected event = "+ expected[index] + ", actual event = " + event + " --- ERROR");
                 }
                 index++;
             }
        } else {
            System.out.println("Number of events expected = " + expected.length + ", number of events reported = " + events.size());
            test_status = "UR4 FAILED - NO MARKS";          
        }       

        System.out.println("\n" + test_status); 
    }

Current Output:

Process-0 is running on Processor-0
Process-1 is running on Processor-1
Process-1 is added in readyQueue
Process-2 is scheduled running on Processor-1
Process-2 is added in readyQueueStart
Process-2 is added in readyQueue
Process-1 is scheduled running on Processor-1
Process-1 is added in readyQueue
Process-2 is scheduled running on Processor-1
Process-2 is added in readyQueue
Process-1 is scheduled running on Processor-1
Process-1 is terminated
Process-2 is scheduled running on Processor-1
Process-2 is terminated
Process-0 is already running on Processor-0
Process-0 is already running on Processor-0
Process-0 is terminated

UR4 - NOW CHECKING
Expected event = pid=0, session=0, actual event = pid=0, session=0 --- MATCH
Expected event = pid=1, session=0, actual event = pid=1, session=0 --- MATCH
Expected event = pid=2, session=0, actual event = pid=2, session=0 --- MATCH
Expected event = pid=1, session=1, actual event = pid=1, session=1 --- MATCH
Expected event = pid=2, session=1, actual event = pid=2, session=1 --- MATCH
Expected event = pid=1, session=2, actual event = pid=1, session=2 --- MATCH
Expected event = pid=2, session=2, actual event = pid=1, session=3 --- ERROR
Expected event = pid=1, session=3, actual event = pid=2, session=2 --- ERROR
Expected event = pid=2, session=3, actual event = pid=2, session=3 --- MATCH
Expected event = pid=0, session=1, actual event = pid=0, session=1 --- MATCH
Expected event = pid=0, session=2, actual event = pid=0, session=2 --- MATCH
Expected event = pid=0, session=3, actual event = pid=0, session=3 --- MATCH
  1. Thread safe' and 'synchronized' classes (e.g. those in java.util.concurrent) other than the two imported above MUST not be used.
  2. keyword 'synchronized', or any other thread safe classes or mechanisms are not allowed
  3. any delays or 'busy waiting' (spin lock) methods are not allowed
0

There are 0 answers