Experimental time slice rotation scheduling algorithm (Java)

1, Experiment name

Experiment (I) multi-channel program, process and time-sharing system simulation

2, Experimental purpose

Deepen the understanding of process management in multi-channel system, understand various states of processes and their conversion process, the setting of time slice in time-sharing system and the scheduling process of processes at the beginning and end of time slice.

3, Experiment contents and requirements

(1) The programming language is used to simulate the process scheduling of multiple processes according to the time slice rotation scheduling algorithm in the time-sharing system;
(2) Suppose there are five processes A, B, C, D and E. their arrival time and service request time are respectively:
Process name A B C D E
Arrival time 0 1 2 3 4
Service time 4 3 4 2 4
The time slice size is 1. Use the program to simulate the scheduling and execution process of five processes A, B, C, D and E rotating according to the time slice, and calculate the turnover time and weighted turnover time.
(3) The time slice size is 2. Use the program to simulate the scheduling and execution process of five processes A, B, C, D and E rotating according to the time slice, and calculate the turnover time and weighted turnover time.
(4) The time slice size is 4. Use the program to simulate the scheduling and execution process of five processes A, B, C, D and E rotating according to the time slice, and calculate the turnover time and weighted turnover time.

4, Experimental design

package com.symc.dsaa.os.test1;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Scanner;

/**
 * analysis:
 * First, for processes, each Process has attributes such as name, arrival time and service time. We encapsulate it into a Process object,
 * And add getter, setter methods and constructors.
 * Second, for the sequence of simulating this process, we need to create multiple processes to test. In the process of execution, they are executed in turn,
 * Only one process can be executed at a time. The remaining processes need a data structure to store the processes waiting for execution, that is, the ready queue,
 * I recommend using queue s here
 * Third, the use of queues. Queue is a linear structure with first in first out characteristics, and what we use is that it can only go out from the head of the team and in from the tail of the team
 * The characteristics of the process put into the queue, so that it can be processed through the time slice. Suppose that the time slice here is 1 second, then the time slice of this process after processing
 * The service time is subtracted by 1 second. Here, it is judged whether the execution is completed. If it is less than or equal to 0, it means that the execution is completed. If it is greater than 0,
 * If the instruction is not completed, put it at the end of the queue and continue to operate the next process.
 * Fourth, in our experiment, we need to complete these four questions, which correspond to different time slices, so our program should be flexible and can be implemented at the same time
 * Various needs.
 */
public class TimeAround {

    /**
     * Variable introduction:
     * ArrayList<Process> list: Define a collection for storing the created processes
     * <p>
     * int CPURun: It is used to record the execution time of the CPU. For example, if we specify the five processes in the topic and run in a single thread,
     * It must be the sum of their service time, that is, the running time of the program is 4 + 3 + 4 + 2 + 4 = 17
     * <p>
     * int num: We can customize the number of tasks (processes)
     * <p>
     * int[] serveTimes: The running time used to store the process, that is, the initial service time, is used to calculate the weighted turnaround time
     *
     * int timeSliceļ¼›Defines the size of the time slice
     * <p>
     * int finishedTime: The end time of the process, which is used to calculate the turnaround time
     * <p>
     * double floatWi:Weighted turnaround time, double type is used here
     * <p>
     * ArrayDeque<Process> deque: Define queue, which is the core data structure of this experiment, with detailed comments in the code
     *
     * @param args
     */
    public static void main(String[] args) {

        ArrayList<Process> list = new ArrayList<>();
        int CPURun = 0;//int CPURun: used to record CPU execution time
        int finishedTime = 0;
        //int finishedTime: the time when the running of the process ends. It is used to calculate the turnaround time

        System.out.println("Please enter the number of processes:");
        int num = new Scanner(System.in).nextInt();
        int[] serveTimes = new int[num];
        //int[] serveTimes: used to store the running time of the process and calculate the weighted turnaround time

        for (int i = 0; i < num; i++) {
            System.out.println("Please give it to the third party" + (i + 1) + "Process name:");
            Process initProcess = Process.createInitProcess();
            CPURun += initProcess.getServeTime();
            serveTimes[i] = initProcess.getServeTime();
            initProcess.setIndex(i);
            list.add(initProcess);
        }

        System.out.println("Please set the time slice size(s): ");
        int timeSlice = new Scanner(System.in).nextInt();
        //int timeSliceļ¼› Defines the size of the time slice
        ArrayDeque<Process> deque = new ArrayDeque<Process>(num);
        Process process;
        for (int i = 0; i < CPURun; i++) {
            if (i == 0) {
                System.out.println("The first" + i + "Seconds:");
            }
            //Every second, a new process is added to the end of the queue
            if (i < num) {
                process = list.get(i);
                deque.offerLast(process);
                System.out.println("process" + process.getName() + "First arrival ready queue");
            }
            System.out.println("process" + deque.getFirst().getName() + "Executing...");

            System.out.println("The current ready queue is as follows:;");
            for (Process task : deque) {
                if (task.getName().equals(deque.getFirst())) {
                    continue;
                }
                System.out.print(task.getName() + "\t");
            }
            System.out.println();
            System.out.println("----------------------------------------");
            if (i != 0) {
                System.out.println("The first" + i + "Seconds:");
            }

            if (i % timeSlice != 0) {
                continue;
            }
            //Resetservertime refresh service time,

            Process process1 = deque.pollFirst().resetServeTime(timeSlice);
            if (process1.isAchieved()) {
                System.out.println("process" + process1.getName() + "End of execution!");
                finishedTime = i + process1.getServeTime();
                System.out.println("process" + process1.getName() + "The turnaround time is:");
                System.out.println(finishedTime - process1.getArriveTime());
                System.out.println("process" + process1.getName() + "The weighted turnaround time is:");
                double floatWi =
                        (finishedTime - process1.getArriveTime()) / serveTimes[process1.getIndex()];
                System.out.println(floatWi);
            } else {
                deque.offerLast(process1);
                System.out.println("process" + process1.getName() + "Enter ready queue");
            }
        }
    }


}

package com.symc.dsaa.os.test1;

import java.util.Scanner;

public class Process {

    private String name;
    private int arriveTime;
    private int serveTime;

    private int index;

    public Process() {
    }

    public Process(String name, int arriveTime, int serveTime) {
        this.name = name;
        this.arriveTime = arriveTime;
        this.serveTime = serveTime;
    }

    public boolean isAchieved() {
        if (serveTime <= 0) {
            return true;
        }
        return false;
    }

    public static Process createInitProcess() {//Create initialization process
        Process process = new Process();
        Scanner sc = new Scanner(System.in);
        process.setName(sc.next());
        System.out.println("Please enter the process" + process.getName() + "Arrival time of:");
        process.setArriveTime(sc.nextInt());
        System.out.println("Please enter the process" + process.getName() + "Service time:");
        process.setServeTime(sc.nextInt());
        return process;
    }


    public Process resetServeTime(int timeSlice) {//Time slice size when a process is taken out of the queue and executed, the service time is reduced after time slice processing
        this.serveTime = this.serveTime - timeSlice;
        return this;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getArriveTime() {
        return arriveTime;
    }

    public void setArriveTime(int arriveTime) {
        this.arriveTime = arriveTime;
    }

    public int getServeTime() {
        return serveTime;
    }

    public void setServeTime(int serveTime) {
        this.serveTime = serveTime;
    }

    public int getIndex() {
        return index;
    }

    public void setIndex(int index) {
        this.index = index;
    }
}

5, Experimental steps and results

1. Experimental content
Run the program: input data according to the topic requirements
You need to enter the number of processes, the name of each process, arrival time and service time, and set the size of the time slice.

2. Experimental results



6, Problems and solutions in the experiment

Question 1: the idea of program implementation

At the beginning, I considered using a real-time or dynamic implementation of process execution according to the sequence of time slices, and using the collection of delayqueues of non blocking queues. In this way, I didn't fully grasp the implementation principle of the queue and API, resulting in many problems. I even rewritten the source code of the collection to achieve my purpose, used object cloning technology, and created two secure threads to add new processes and recycled processes to the queue. Although the effect of dynamic real-time addition of columns is realized, some execution effects are not good. Because I did not control the order between the two threads and the main thread, the results are difficult to understand.
Solution: I want to achieve the simulation results, not focus on the process, so I just need to let it run out of the results in this order. Moreover, each dynamic execution needs to wait. For example, the five tasks in the question have a total service time of 17 seconds, and we still need to wait 17 seconds to see the complete results we want. Moreover, it is easy to control and implement by using ordinary queue and single route. This shows the importance of algorithm thinking. It is much easier to turn process oriented thinking into result oriented thinking.

Problem 2: create processes (tasks) and process storage in an orderly manner

My idea is that users first set all processes and then Run them together (Run means running), but the set programs can't be used immediately and need to be stored.
Solution: after encapsulating the process, I add a static method for quickly creating process objects in this class. Its return value is the initialized process according to the user's settings. Use the for loop to batch create, and use ArrayList to store these processes.

Question 3: when to take a process out of the queue and put it at the end

You should know that the executing program is executed according to the time slice cycle. It is also a troublesome thing to get the program out and put it into the ready queue according to the order of this specified interval. At the beginning, I wrote the program according to the time slice of 1 second. This ran very smoothly, but if it was changed to 2 seconds or 4 seconds, it would not be obedient.
Solution: I added this line of code:
if (i % timeSlice != 0) {
continue;
}
It is implemented in this way. i is the current time and timeSlice is the time slice. If the current time point can be implemented in this way, i is the current time and timeSlice is the time slice. If the current time point can be divided, it means that this is the time when the process has executed once, followed by the code of the exchange process. If it cannot be divided, It means that the time slice has not been used up. End this cycle and don't let it run through the following code. For example, the time slice size is 3. If i=6, this is the end time of the second round of time slice. At this time, the process should be exchanged; If i=5 and cannot be divided, i'm sorry. i can't exchange processes. i need to wait another second.

Problem 4: processing after each execution of the process and putting it into the end of the ready queue

First of all, you should know whether it has been executed. If it has been executed, you don't have to put it at the end of the team. If it hasn't been executed, you have to put it at the end of the team. Before putting it at the end of the team, the corresponding service time should be minus the time slice.
Solution: the good thing is to use the object-oriented method. You can directly modify the service time through the set method. For judging whether the execution is completed, I added a boolean method to the process class. If the service time is equal to or less than 0, it means that it is completed. I also defined a reset method to reduce the service time of the process. The collection of queues has API s for fetching and putting elements.

7, Conclusion

The time slice size should be moderate.

Tags: Operating System

Posted on Thu, 18 Nov 2021 19:09:37 -0500 by JeDi58