⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dispatcherthread.java

📁 一个用于排队系统仿真的开源软件,有非常形象的图象仿真过程!
💻 JAVA
字号:
/**    
  * Copyright (C) 2006, Laboratorio di Valutazione delle Prestazioni - Politecnico di Milano

  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.

  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.

  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
  
package jmt.gui.common.controller;

import jmt.engine.simDispatcher.Dispatcher_jSIMschema;
import jmt.gui.common.definitions.AbortMeasure;
import jmt.gui.common.definitions.GuiInterface;
import jmt.gui.common.definitions.ResultsModel;
import jmt.gui.common.definitions.SimulationDefinition;
import jmt.gui.common.panels.ResultsWindow;
import jmt.gui.jmodel.controller.Mediator;
import jmt.gui.jmodel.controller.SimulationStateChecker;

import java.awt.*;
import java.io.File;

/**
 * <p>Title: Dispatcher Thread</p>
 * <p>Description: This thread is responsable for dispatching simulation. If simulation max time has
 * been specified, an inner thread will be used to stop simulation after that time. We don't rely
 * on engine method as it doesn't appear to work properly.</p>
 * 
 * @author Bertoli Marco
 *         Date: 8-set-2005
 *         Time: 11.40.46
 *
 * Modified by Francesco D'Aquino 9/11/2005
 */
public class DispatcherThread extends Thread implements AbortMeasure {
    private SimulationStateChecker simStateChecker;
    private Dispatcher_jSIMschema simulator;
    private SimulationDefinition sd;
    private GuiInterface gui;
    private TimerThread timer = null;
    private PollerThread poller = null;
    ResultsModel results;

    /**
     * Construct a new Dispatcher Thread
     * @param gui reference to current gui object (can be JSIMMain or Mediator)
     * @param sd Reference to Simulation Definition data structure
     * @param results data structure where simulation results should be saved
     */
    public DispatcherThread(GuiInterface gui, SimulationDefinition sd, ResultsModel results) {
        this.sd = sd;
        this.gui = gui;
        this.results = results;
        poller = new PollerThread(sd.getPollingInterval(), this);
        // Avoid hanging the system during execution
        this.setPriority(Thread.MIN_PRIORITY);
    }

    /**
     * Run method. This method will simply start simualtion, it is designed to be called only
     * after startSimulation has been called.
     */
    public void run() {
        if (timer != null)
            timer.start();
        poller.start();
        try {
            simulator.solveModel();
        }
        catch (OutOfMemoryError err) {
            simulator.abortAllMeasures();
            simulator.killSimulation();
            gui.showErrorMessage("Out of memory error. Try to run Java Virtual Machine with more heap size (-Xmx<num>m)");
        }
        catch (Exception ex) {
            simulator.abortAllMeasures();
            simulator.killSimulation();
            gui.handleException(ex);
        }
        if (timer != null)
            timer.kill();
        gui.changeSimActionsState(true, false, false);
        results.refresh(1);
    }

    /**
     * This method starts simualtion, given simulation XML file
     * @param simulationFile file where simulation model is stored
     */
    public void startSimulation(File simulationFile) {
        simulator = new Dispatcher_jSIMschema(simulationFile);
        // ----------- Francesco D'Aquino ---------------
        if (sd.isAnimationEnabled()) {
            //if it is the first time create a new simStateChecker
            /*if (simStateChecker == null)*/ simStateChecker = new SimulationStateChecker((Mediator)gui,simulator);
            //else renew the existing one
            //else simStateChecker.renew((Mediator)gui,simulator);
        }
        // ----------- end Francesco D'Aquino -----------
        // If needed sets simulation seed
        if (!sd.getUseRandomSeed())
            simulator.setSimulationSeed(sd.getSimulationSeed().longValue());
        // If a time maximum time is specified, initialize all stuff related
        if (sd.getMaximumDuration().longValue() > 0) {
            timer = new TimerThread(this, sd.getMaximumDuration().doubleValue());
        }
        gui.changeSimActionsState(false, true, true);
        start();
    }

    /**
     * Pauses current simulation only if it was already started
     */
    public void pauseSimulation() {
        if(simulator != null){
            if (timer != null)
                timer.pause();
            gui.changeSimActionsState(true, false, true);
            simulator.pauseSim();
        }
    }

    /**
     * Stops current simulation, forcing abort of all measures,
     * only if it was already started
     */
    public void stopSimulation() {
        if(simulator != null){
            if (timer != null)
                timer.kill();
            gui.changeSimActionsState(true, false, false);
            simulator.abortAllMeasures();
        }
    }

    /**
     * Restarts current simulation, forcing abort of all measures,
     * only if it was already started
     */
    public void restartSimulation() {
        if(simulator != null){
            if (timer != null)
                timer.restart();
            gui.changeSimActionsState(false, true, true);
            simulator.restartSim();
        }
    }

    /**
     * Aborts a measure, given its index
     * @param index index of the measure to be aborted
     */
    public void abortMeasure(int index) {
        simulator.abortMeasureAtRefresh(index);
    }


    /**
     * Inner thread used to poll
     */
    protected class PollerThread extends Thread {
        protected long interval;
        protected DispatcherThread dispatcher;
        protected boolean initialized = false;
        public PollerThread (double seconds, DispatcherThread dispatcher) {
            interval = Math.round(seconds * 1000);
            this.dispatcher = dispatcher;
        }

        public void run() {
            if (gui instanceof Mediator) ((Mediator)gui).setGraphCursor(new Cursor(Cursor.WAIT_CURSOR));
            // While simulation is not finished, polls at given intervals
            while (!dispatcher.simulator.isFinished()) {
                // Wait to collect results until simulation is really started
                while (!dispatcher.simulator.isStarted() && !dispatcher.simulator.isFinished())
                    try {
                        sleep(500);
                    }
                    catch (InterruptedException ex) {
                        System.err.println("Unexpected InterruptException in PollerThread");
                    }
                // If it's first poll, initialize Results data structure
                if (!initialized) {
                    if (gui instanceof Mediator) ((Mediator)gui).setGraphCursor(new Cursor(Cursor.DEFAULT_CURSOR));
                    dispatcher.simulator.refreshTempMeasures();
                    dispatcher.results.setTempMeasures(dispatcher.simulator.getTempMeasures(), dispatcher.simulator.checkSimProgress());
                    initialized = true;
                    // Sets ResultsWindow
                    gui.setResultsWindow(new ResultsWindow(results, dispatcher));
                    // Shows it
                    if (!(sd.isAnimationEnabled()))gui.showResultsWindow();
                }
                // If it's next one, refresh stored tempMeasures (if simulation is started and not paused)
                else if (!dispatcher.simulator.isPaused()) {
                    dispatcher.simulator.refreshTempMeasures();
                    double progress = dispatcher.simulator.checkSimProgress();
                    // Progress is the biggest between simulation progress and timer progress
                    if (timer != null && timer.getElapsedPercentage() > progress)
                        progress = timer.getElapsedPercentage();
                    dispatcher.results.refresh(progress);
                    // ------------ Francesco D'Aquino -------------------
                    if (sd.isAnimationEnabled()) {
                        if ( !simStateChecker.isInitialized() ) {
                            simStateChecker.initialize();
                        }
                        simStateChecker.getModelState();
                        //simStateChecker.print();
                        simStateChecker.forceDraw();
                    }
                    // -------------end Francesco D'Aquino ---------------
                }

                // Wait for polling interval
                try {
                    sleep(interval);
                }
                catch (InterruptedException ex) {
                    System.out.println("Error: Poller thread interrupted unexpectedly...");
                }
            }
            if (sd.isAnimationEnabled()) {
                simStateChecker.forceRepaint();
                gui.showResultsWindow();
            }
        }
    }



    /**
     * An inner thread used to stop simulation after timeout elapsed
     */
    protected class TimerThread extends Thread {
        protected long residualTime, totalTime;
        protected DispatcherThread dispatcher;
        protected long initialTime;
        // End means normal end of measures, kill forced one
        protected boolean end = false;
        protected boolean killed = false;
        protected boolean paused = false;
        protected final Object lock = new Object();
        public TimerThread (DispatcherThread dispatcher, double maxDuration) {
            this.dispatcher = dispatcher;
            this.residualTime = this.totalTime = Math.round(maxDuration * 1000);
        }

        /**
         * Thread run's method. It will wait until maxDuration has elapsed, then stops
         * simulation.
         */
        public void run() {
            initialTime = System.currentTimeMillis();
            // Wait for residual time. This is true unless pause button is pressed.
            while (!end && !killed) {
                initialTime = System.currentTimeMillis();
                try {
                    synchronized(this) {
                        wait(residualTime);
                    }
                } catch (InterruptedException e) {
                    System.out.println("Error: Timer thread interrupted unexpectedly...");
                }

                residualTime = residualTime - (System.currentTimeMillis() - initialTime);
                if (residualTime <= 100)
                    end = true;

                synchronized(lock) {
                    try {
                        // If end=false we have to wait until restart or kill is told us
                        if (!end && !killed)
                            lock.wait();
                    } catch (InterruptedException e) {
                        System.out.println("Error: Timer thread interrupted unexpectedly...");
                    }
                }
            }
            while(!dispatcher.simulator.isFinished()) {
                dispatcher.stopSimulation();
                // Try to terminate simulation more than once if required.
                try {
                    sleep(500);
                } catch (InterruptedException e) {
                    // Never thrown
                    e.printStackTrace();
                }
            }
        }

        /**
         * This method have to be called when simulation is paused
         */
        public synchronized void pause() {
            // Unblocks first wait in run method, so residualTime is updated
            paused = true;
            notifyAll();
        }

        /**
         * This method have to be called when simulation is restarted after pause
         */
        public synchronized void restart() {
            // Unblocks second wait in run method, so it will restart from the beginning
            synchronized(lock) {
                lock.notifyAll();
                paused = false;
            }
        }

        /**
         * This method have to be called if simulation is stopped or if it ends before timeout has
         * elapsed.
         */
        public synchronized void kill() {
            end = true;
            killed = true;
            synchronized(lock) {
                lock.notifyAll();
            }
            notifyAll();
        }

        /**
         * Returns elapsed time in percentage format
         * @return elapsed time / total time
         */
        public synchronized double getElapsedPercentage() {
            double elapsed;
            if (paused)
                elapsed = 1 - (double)residualTime / (double)totalTime;
            else
                elapsed =  1 - (double)(residualTime - (System.currentTimeMillis() - initialTime)) / (double)totalTime;
            // Fix possible problem when this funcion is called after simulation ends
            if (elapsed > 1)
                elapsed = 1;
            return elapsed;
        }
    }

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -