如何创建MultiServer和客户端 - java模拟

时间:2017-05-20 08:18:27

标签: java random simulation

如何将此代码中的服务器数量更改为增量编号:5,10,15,10,并且在增量期间,我可以检查/计算等待时间?

import java.util.ArrayList;
import java.text.DecimalFormat;

public class Simulate3 {
    private static boolean openPosition;
    private static double fractionAvg = 0.0;
    private static DecimalFormat percent;

    public static void main(String[] args)
    {
        double  Mean_Exponential_iat = 10.0;
        double  Mean_erlang_completion_distribution = 2.0;
        int     Time_until_theEnd_of_WorkDay = 8;
        /**
         * By starting and finishing shift with 1 server, almost 98.484848% of customers wait more than 6 mins with the avg wait time at 218 hours.
         * With 2 servers the avg wait time is 13 hours with 69.1489% waiting more than 6 mins. 
         * With 3 servers the avg waiting time is 26mins with  0% of customers waiting more than 6 mins. 
         * Therefore the optimal allocation will be by assigning 2 servers to start off the shift and when the need arises, open a new position of service.
         * If 1 server alone starts, the fraction in close to 16%. 
         * By starting with 2 servers the fraction is 4.3%.
         */

        int The_number_of_servers_in_the_branch =0;         
        long seed = +5; // The starting seed for the random number generator
        int trials =10;//The number of times the simulation will be repeated for the average statistics

        for (int i = 1; i <= trials; i++)// Conduct a number of trials in order to get the average fraction of customers waiting more than 6 mins. 
                                         //Use different seed in each trial.
        {
        simulateNServers(Mean_Exponential_iat, Mean_erlang_completion_distribution, Time_until_theEnd_of_WorkDay, The_number_of_servers_in_the_branch, seed);
        seed++;

            }

        double trialAvg = fractionAvg/trials;
        percent = new DecimalFormat("0.#%");

        System.out.println("=============================================================================");
    //  System.out.println("////");
        System.out.println("Average percent of task waiting more than 6 minutes (100 trials) : "+  percent.format(trialAvg));

        System.out.println("=============================================================================");



    }

    /**
     * Static method to run a simulation with certain parameters. It outputs the following statistical data.
     * 
     * Average waiting time   : 
     * Server free fraction   : [The percentage of the servers being free]
     * Maximum queue length   : 
     * Total customers arrived: [Total arrivals of customers within the work-day]
     * Total customers served : [Total customers served within the work-day]
     * Total customers >6min  : [Total number of customers that waited more than 6 minutes to be served, within the work-day]
     * fraction               : [Percentage of customers that waited more than 6 minutes in the queue]
     * 
     * @param lambdaA : Mean of exponential inter-arrival distribution.
     *            
     * @param lambdaS : Mean of erlang completion distribution.
     *            
     * @param tEnd : The time until the end of the work-day
     *            
     * @param nserv :  The number of servers in the branch
     *           
     * @param seed 
     */
    public static void simulateNServers(double Mean_Exponential_iat, double Mean_erlang_completion_distribution, double Time_until_theEnd_of_WorkDay, int The_number_of_servers_in_the_branch, long seed) 
    {
        The_number_of_servers_in_the_branch +=5;
        Queue q = new Queue(); // Initializes up the Queue
        ArrayList<Server> serverFree = new ArrayList<Server>(); // Create list of servers
        MyRandom r = new MyRandom(seed); // Initializes the random number generator
        int k = 10; // Initializes the kappa of the Erlang distribution

        double clock = 0; // Start of time
        double Time_to_next_arrival = 0.0; // Time to next arrival
        //double[] tnc = new double[nserv]; // Times of size nserv of completion for every server [i]
                                            // 
        double endTime = Time_until_theEnd_of_WorkDay; // Minutes until endtime
        int Number_of_Total_Events = 0; // Number of total events
        int Number_of_total_arrivals = 0; // Number of total arrivals
        double The_Time_to_the_NextEvent = 0.0; // The time to the next event
        int Max_Q_length = 0; // Max Q length

        double Time_free_at_each_instance = 0.0; // Time free at each instance
        double Total_server_free_time = 0.0; // Total server free time
        double ttServerFree = 0.0;
        double Total_Waiting_Time = 0.0; // Total waiting time
        double Total_Number_of_Tasks = 0.0; // Total Number of Customers
        double Number_of_customers_waiting_more_than_6Minutes = 0.0; // Number of customers waiting more than 6 minutes
        int The_Total_Number_of_Servers_BUSY_for_all_events = 0;    // The total number of servers busy for all events  
        int prevHour = 0;       // Keeping track of which hour has finished
        int hourStartEvent = 0;
        int serverSum = 5;
        double serverHourlyAvg = 0.0;


        for (int i = 0; i < The_number_of_servers_in_the_branch; i++)  // Initialize the servers' status
            {
            serverFree.add(new Server(true));
            }


        Server tmpSrv = serverFree.get(0); // Initialise the first completion time to 0.0
        tmpSrv.setTnc(0.0);
        serverFree.set(0, tmpSrv);

        // Primary simulation loop
        while (true) {

            boolean arrivalEvent = false; // The type of the next event, arrival
                                            // or otherwise
            boolean serviceEvent = false; // The type of the next event, service
                                            // or otherwise
            // Keep track of previous event for server free statistics
            double prevEvent = 0.0;
            // Check if the length of the Q is the largest
            if (q.length() > Max_Q_length) 
                {
                Max_Q_length = q.length();
                }
                //Keep track of the fraction of customers waiting more than 6mins
                //This should not exceed 5% on average
            double fraction = Number_of_customers_waiting_more_than_6Minutes / Total_Number_of_Tasks;

            //System.out.println("============================================ " );

            //System.out.println("fraction: "   + fraction); // Print out the fraction per event

            int servers=serverFree.size(); // Prints out the number of servers

            //System.out.println("============================================ " );
            //System.out.println("nserv: "  + nserv);
            // Keep track of how many servers are busy
            The_Total_Number_of_Servers_BUSY_for_all_events += busyServersNo(serverFree);   
            double tnc;// Get the next completion time from all servers
            Server tmp = getNextTNC(serverFree); 
            if(tmp!=null) tnc = tmp.getTnc();
            else tnc=Double.POSITIVE_INFINITY;
            int tnc_index = serverFree.indexOf(tmp);

            // Check if the next event is a feasible arrival time
            The_Time_to_the_NextEvent  = Math.min(Time_to_next_arrival, tnc);
            if (The_Time_to_the_NextEvent  == Time_to_next_arrival && Time_to_next_arrival != tnc) 
            {
                arrivalEvent = true;
                serviceEvent = false;
            } else if (The_Time_to_the_NextEvent  == tnc && Time_to_next_arrival != tnc) 
            {
                serviceEvent = true;
                arrivalEvent = false;
            } else if (Time_to_next_arrival == tnc) {
                arrivalEvent = true;
            }

            // Update the clock
            if (The_Time_to_the_NextEvent  != Double.POSITIVE_INFINITY) {
                prevEvent = clock;
                clock = The_Time_to_the_NextEvent ;
            }

            /**
             * In this block I'll be keeping some statistics for the average
             * allocation of servers per hour
             */
            int currHour=(int) clock;
                if(currHour==prevHour)
                {
                serverSum+=servers;
                }
                else if (currHour>=prevHour)
                {
                serverHourlyAvg= (double) serverSum/(Number_of_Total_Events - hourStartEvent);

                System.out.println("Avg servers for hour    "+ currHour  +  " : "+  serverHourlyAvg);
                serverSum = 0;
                hourStartEvent=   Number_of_Total_Events ;
                prevHour=currHour;
            }

            /**
             * Every time the cycle begins there needs to be a check whether the optimality constraint is met. 
             * This constraint is that the queue is no larger than 6 customers. 
             * If it is not, then the algorithm needs to set up a flag that will increase the number of servers until the constraint is satisfied.
             * 
             */
            if (q.length()>10) 
            {
                openPosition=true;
            }
                else openPosition=false;

            int id = getFreeServer(serverFree); // Get the index of the next available server

            if (q.isEmpty() && clock >= endTime && tnc == Double.POSITIVE_INFINITY) // BRANCH_1// Check if the condition to stop the simulation has been met.
            {
                percent = new DecimalFormat("0.0#%");
                System.out.println("==================================================================");
                System.out.println("The number of servers : "   + servers);
                System.out.println("Maximum queue length: " + Max_Q_length);
                System.out.println("Total tasks arrived: " + Number_of_total_arrivals);
                System.out.println("Total tasks served :    " + (int) Total_Number_of_Tasks);
                System.out.println("The_number_of_servers_in_the_branch : " + The_number_of_servers_in_the_branch);
                System.out.println("Average waiting time: " + 60*  Total_Waiting_Time / Total_Number_of_Tasks +   "    minutes");
                System.out.println("Server free fraction: " + percent.format(Total_server_free_time / ttServerFree));

                System.out.println("Total tasks waiting >6min  : " + (int) Number_of_customers_waiting_more_than_6Minutes);
                System.out.println(" fraction              : "  + fraction);
                fractionAvg+=fraction;
                break;

            }


            if (arrivalEvent && clock < endTime)  // BRANCH_2// This is an arrival event and the end time is not reached
                {
                if (id != -1)
                    Time_free_at_each_instance = clock - prevEvent;
                    ttServerFree += Time_free_at_each_instance;
                    Total_server_free_time  += Time_free_at_each_instance * freeServersNo(serverFree);

                if (freeServersNo(serverFree) != 0) // Report how many servers are free and for how long
                    //System.out.println(freeServersNo(serverFree) + " server(s) are free for " + timeFree + " hours. Total= " + ttServer);

                    Time_to_next_arrival = clock + r.nextExponential(getLambda(clock));// Sample for next arrival time so long that it doens't exceed endTime
                        if (Time_to_next_arrival > Time_until_theEnd_of_WorkDay) 
                        {
                            Time_to_next_arrival = Double.POSITIVE_INFINITY;
                        }
                        Number_of_total_arrivals++;


                if (id != -1) // BRANCH_3_YES // Inner conditional loop to check if there is at least one server free
                    { // Mark the server as busy by replacing the object in the arraylist
                    Server tmpSrv0 = serverFree.get(id);
                    tmpSrv0.setState(false);                                    
                    tmpSrv0.setTnc(clock + r.nextErlang(k, Mean_erlang_completion_distribution)); // Sample for time of next completion
                    serverFree.set(id, tmpSrv0);
                    } 
                else {// BRANCH_3_NO                    
                    q.put(clock);// Put person in the queue
                    // If there is need for servers add one here
                    if (openPosition) serverFree.add(new Server(true));
                }
                // Print out the arrival event
                System.out.println(" Number_of_Total_Events arrival: " + Number_of_Total_Events + "  " + "" + " Queue length: " + q.length() + " Time: " + clock);

                if (q.isEmpty()) 
                {
                    // System.out.println("Guy is served, has waited: 0.0");
                    Total_Number_of_Tasks++;
                }
            } 

            else 
                {               
                if (serviceEvent) // BRANCH_4_YES// This is a service completion event
                    {
                    if (id != -1)
                        Time_free_at_each_instance = clock - prevEvent;
                        ttServerFree += Time_free_at_each_instance;
                        Total_server_free_time  += Time_free_at_each_instance * freeServersNo(serverFree);

                    if (freeServersNo(serverFree) != 0)// Report how many servers are free and for how long

                    System.out.println(freeServersNo(serverFree) + " server(s) are free for " + Time_free_at_each_instance + " hours." + " Total_server_free_time  : " + Total_server_free_time );
                    // BRANCH_5_YES// Inner conditional loop to check if the
                    // queue is empty
                    if (q.isEmpty()) 
                    {

                        // If there is no more need; release the additional server
                        if (!openPosition && serverFree.size()>The_number_of_servers_in_the_branch && id!=-1) serverFree.remove(id);

                        // Get the first busy server and release them
                        int busy = serverFree.indexOf(getNextTNC(serverFree));
                        if (busy != -1){
                            // Mark the server as busy by replacing the object in the arraylist
                            Server tmpSrv1 = serverFree.get(busy);
                            tmpSrv1.setState(true);
                            serverFree.set(busy, tmpSrv1);
                        }

                        if (busy != -1){
                            Server tmpSrv2 = serverFree.get(busy);
                            tmpSrv2.setTnc(Double.POSITIVE_INFINITY);
                            serverFree.set(busy, tmpSrv2);
                        }


                    }// End of yes in Condition 5
                    else {// BRANCH_5_NO//
                            // Get person from queue
                        double t = q.get();

                        // Log the served customer
                        Total_Number_of_Tasks++;
                        // Check which customers waited more than 6 minutes (0.1
                        // of the hour)
                        if ((clock - t) > 0.1) 
                        {

                            Number_of_customers_waiting_more_than_6Minutes++; // If it took more than 6 minutes to serve, log it.
                        }
                        System.out.println("Tasks is served, has waited: "      + (clock - t));

                        Total_Waiting_Time += (clock - t);  // Update the sum of waiting times

                        // Sample for time of next completion
                        Server tmpSrv3 = serverFree.get(tnc_index);
                        tmpSrv3.setTnc(clock + r.nextErlang(k, Mean_erlang_completion_distribution));
                        serverFree.set(tnc_index, tmpSrv3);

                    }// End of no in Condition 5
                        // Write out the Completion of the event
                    int event = tnc_index + 1;
                    System.out.println(" Number_of_Total_Events : "+ Number_of_Total_Events + "  " + "completed : " + event + "  " + "Queue length: " + q.length() + " Time: " + clock);

                }// End of Condition 4
                else {// BRANCH_4_NO//
                        // Set next arrival time to very large number
                    Time_to_next_arrival = Double.POSITIVE_INFINITY;
                }// End of Infinite arrival time
            }// End of no in Condition 2
                // Increment the number of events
            Number_of_Total_Events++;
        }// End of while loop
    }// End of static main method



    /**
     * Method to get the appropriate average of arriving customers per hour of service. The distributions were provided by the manager. 
     * They can be changed to any measured distribution.
     * 
     * @param Clock
     *            The current time
     * @return The average customers arriving for this hour
     */
    private static double getLambda(double clock) 
    {
        switch ((int) clock) 
        {
        case 0:
            return 1.0;
        case 1:
            return 2.0;
        case 2:
            return 3.0;
        case 3:
            return 4.0;
        case 4:
            return 5.0;
        case 5:
            return 6.0;
        case 6:
            return 7.0;
        case 7:
            return 8.0;
        default:
            return 0;
        }

    }


    /**
     * Find the first server that is free.
     * @param serverFree The arraylist in which to look for a free server
     * @return  The index of the position of the first free server
     */
    private static int getFreeServer(ArrayList<Server> serverFree) {
        for (Server server : serverFree) {
            boolean state = server.isState();
            if (state){
                return serverFree.indexOf(server);
            }
        }return -1;
    }// End of getFreeServer method

    /**
     * Find the first server that is busy.
     * @param serverFree The arraylist in which to look for a busy server
     * @return The index of the position of the first busy server
     */
    private static int getBusyServer(ArrayList<Server> serverFree) 
    {
        for (Server server : serverFree) 
        {
            boolean state = server.isState();
            if (state){
                return serverFree.indexOf(server);
            }
        }return -1;
    }// End of getFreeServer method

    /**
     * Count the free servers
     * @param serverFree The arraylist in which to look for a free server
     * @return The number of servers that are free
     */
    private static int freeServersNo(ArrayList<Server> serverFree)
    {
        int servers = 0;
        for (Server server : serverFree) {
            boolean state = server.isState();
            if (state) 
                servers++;
        }
        return servers;
    }// End of freeServersNo method

    /**
     * Count the busy servers
     * @param serverFree The arraylist in which to look for a busy server
     * @return The number of servers that are busy
     */
    private static int busyServersNo(ArrayList<Server> serverFree)
    {
        int servers =0;
        for (Server server : serverFree) {
            boolean state = server.isState();
            if (!state) 
                servers++;

        }
        return servers;
    }// End of busyServersNo method


    /**
     * Find the server with the lowest completion time
     * @param tnc_min The arraylist to search for completion times 
     * @return The index of the lowest time of completion
     */
    private static Server getNextTNC(ArrayList<Server> serverFree) 
    {
        double tnc_min = Double.POSITIVE_INFINITY;
        Server index = null;
        for (Server server : serverFree) 
        {
            if(server.getTnc() < tnc_min) {
                tnc_min = server.getTnc();
                index=server;
            }

        }
        return index;
    }// End of getNextTNC method
}// End of Class

1 个答案:

答案 0 :(得分:0)

只需创建一个额外的函数并将服务器数量作为参数传递,如下所示:

iptables -t nat -A OUTPUT -p tcp --dport 80 -m owner ! --uid-owner 0 -j DNAT --to 127.0.0.1:8080

您可以在模拟结束时使用以下表达式获取等待时间:&#34; 60 * ttwait / ttServed&#34;:

    public static void main(String[] args) {


        double lambdaA = 58.0;
        double lambdaS = 30.0;
        double tEnd = 8.0;
        /**
         * By starting and finishing shift with 1 server, almost 98.484848% of
         * customers wait more than 6 mins with the avg wait time at 218 hours.
         * With 2 servers the avg wait time is 13 hours with 69.1489% waiting
         * more than 6 mins. With 3 servers the avg waiting time is 26mins with
         * 0% of customers waiting more than 6 mins. Therefore the optimal
         * allocation will be by assigning 2 servers to start off the shift and
         * when the need arises, open a new position of service. If 1 server
         * alone starts, the fraction in close to 16%. By starting with 2
         * servers the fraction is 4.3%.
         */

    //  int nserv = 2;
        int[] servers = {5, 10, 15, 10};

        for (int nserv : servers) {
            simulateServers(lambdaA, lambdaS, tEnd, nserv);
        }

    }

    private static void simulateServers(double lambdaA, double lambdaS, double tEnd, int nserv) {


        // The starting seed for the random number generator
        long seed = 12342;

        //The number of times the simulation will be repeated for the average statistics
        int trials = 100;

        // Conduct a number of trials in order to get the average fraction of customers
        // waiting more than 6 mins. Use different seed in each trial.
        for (int i = 1; i <= trials; i++) {
            simulateNServers(lambdaA, lambdaS, tEnd, nserv, seed);
            seed++;
        }
        double trialAvg = fractionAvg / trials;
        percent = new DecimalFormat("0.#%");
        System.out.println("=============================================================================");
        System.out.println();
        System.out.println("Average percent of customers waiting more than 6 minutes (100 trials) : 

" + percent.format(trialAvg));
        }

// Get the index of the next available server
int id = getFreeServer(serverFree);
// BRANCH_1// Check if the condition to stop the simulation has been met.
if (q.isEmpty() && clock >= endTime
    && tnc == Double.POSITIVE_INFINITY) {
percent = new DecimalFormat("0.0#%");
System.out.println("Average waiting time: " + 60 * ttwait
    / ttServed + " minutes");