Java Tutorial/Development/Stop Watch

Материал из Java эксперт
Перейти к: навигация, поиск

Provides the programatic analog of a physical stop watch

   <source lang="java">

/* Copyright (c) 2001-2009, The HSQL Development Group

* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the HSQL Development Group nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

/**

* Provides the programatic analog of a physical stop watch. 
*
* The watch can be started, stopped and zeroed and can be queried for
* elapsed running time.  The watch accumulates elapsed time over starts
* and stops such that only the time actually spent running is recorded.
* If the watch is zeroed, then the accumulated time is discarded and
* the watch starts again with zero acumulated time. 
*
* @author boucherb@users
* @version 1.7.2
* @since 1.7.2
*/

public class StopWatch {

   /**
    * The last time this object made the transition
    * from stopped to running state, as reported
    * by System.currentTimeMillis().
    */
   private long startTime;
   private long lastStart;
   /**
    * The accumulated running time of this object since
    * it was last zeroed.
    */
   private long total;
   /** Flags if this object is started or stopped. */
   boolean running = false;
   /** Creates, zeros, and starts a new StopWatch */
   public StopWatch() {
       this(true);
   }
   /** Creates, zeros, and starts a new StopWatch */
   public StopWatch(boolean start) {
       if (start) {
           start();
       }
   }
   /**
    * Retrieves the accumulated time this object has spent running since
    * it was last zeroed.
    * @return the accumulated time this object has spent running since
    * it was last zeroed.
    */
   public long elapsedTime() {
       if (running) {
           return total + System.currentTimeMillis() - startTime;
       } else {
           return total;
       }
   }
   /**
    * Retrieves the accumulated time this object has spent running since
    * it was last started.
    * @return the accumulated time this object has spent running since
    * it was last started.
    */
   public long currentElapsedTime() {
       if (running) {
           return System.currentTimeMillis() - startTime;
       } else {
           return 0;
       }
   }
   /** Zeros accumulated running time and restarts this object. */
   public void zero() {
       total = 0;
       start();
   }
   /**
    * Ensures that this object is in the running state.  If this object is not
    * running, then the call has the effect of setting the startTime
    * attribute to the current value of System.currentTimeMillis() and setting
    * the running attribute to true.
    */
   public void start() {
       startTime = System.currentTimeMillis();
       running   = true;
   }
   /**
    * Ensures that this object is in the stopped state.  If this object is
    * in the running state, then this has the effect of adding to the
    * total attribute the elapsed time since the last transition
    * from stopped to running state and sets the running attribute
    * to false. If this object is not in the running state, this call has no
    * effect.
    */
   public void stop() {
       if (running) {
           total   += System.currentTimeMillis() - startTime;
           running = false;
       }
   }
   public void mark() {
       stop();
       start();
   }
   /**
    * Retrieves prefix + " in " + elapsedTime() + " ms."
    * @param prefix The string to use as a prefix
    * @return prefix + " in " + elapsedTime() + " ms."
    */
   public String elapsedTimeToMessage(String prefix) {
       return prefix + " in " + elapsedTime() + " ms.";
   }
   /**
    * Retrieves prefix + " in " + elapsedTime() + " ms."
    * @param prefix The string to use as a prefix
    * @return prefix + " in " + elapsedTime() + " ms."
    */
   public String currentElapsedTimeToMessage(String prefix) {
       return prefix + " in " + currentElapsedTime() + " ms.";
   }
   /**
    * Retrieves the internal state of this object, as a String.
    *
    * The retreived value is:
    *
*
     *    super.toString() +
     *    "[running=" +
     *    running +
     *    ", startTime=" +
     *    startTime +
     *    ", total=" +
     *    total + "]";
     * 
    * @return the state of this object, as a String
    */
   public String toString() {
       return super.toString() + "[running=" + running + ", startTime="
              + startTime + ", total=" + total + "]";
   }

}</source>





Simple stop watch

   <source lang="java">

/*

* Copyright 2002-2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import java.text.NumberFormat; import java.util.LinkedList; import java.util.List; /**

* Simple stop watch, allowing for timing of a number of tasks,
* exposing total running time and running time for each named task.
*
* Conceals use of System.currentTimeMillis(), improving the
* readability of application code and reducing the likelihood of calculation errors.
*
* Note that this object is not designed to be thread-safe and does not
* use synchronization.
*
* This class is normally used to verify performance during proof-of-concepts
* and in development, rather than as part of production applications.
*
* @author Rod Johnson
* @author Juergen Hoeller
* @since May 2, 2001
*/

public class StopWatch {

 /**
  * Identifier of this stop watch.
  * Handy when we have output from multiple stop watches
  * and need to distinguish between them in log or console output.
  */
 private final String id;
 private boolean keepTaskList = true;
 /** List of TaskInfo objects */
 private final List taskList = new LinkedList();
 /** Start time of the current task */
 private long startTimeMillis;
 /** Is the stop watch currently running? */
 private boolean running;
 /** Name of the current task */
 private String currentTaskName;
 private TaskInfo lastTaskInfo;
 private int taskCount;
 /** Total running time */
 private long totalTimeMillis;
 /**
  * Construct a new stop watch. Does not start any task.
  */
 public StopWatch() {
   this.id = "";
 }
 /**
  * Construct a new stop watch with the given id.
  * Does not start any task.
  * @param id identifier for this stop watch.
  * Handy when we have output from multiple stop watches
  * and need to distinguish between them.
  */
 public StopWatch(String id) {
   this.id = id;
 }
 /**
  * Determine whether the TaskInfo array is built over time. Set this to
  * "false" when using a StopWatch for millions of intervals, or the task
  * info structure will consume excessive memory. Default is "true".
  */
 public void setKeepTaskList(boolean keepTaskList) {
   this.keepTaskList = keepTaskList;
 }
 /**
  * Start an unnamed task. The results are undefined if {@link #stop()}
  * or timing methods are called without invoking this method.
  * @see #stop()
  */
 public void start() throws IllegalStateException {
   start("");
 }
 /**
  * Start a named task. The results are undefined if {@link #stop()}
  * or timing methods are called without invoking this method.
  * @param taskName the name of the task to start
  * @see #stop()
  */
 public void start(String taskName) throws IllegalStateException {
   if (this.running) {
     throw new IllegalStateException("Can"t start StopWatch: it"s already running");
   }
   this.startTimeMillis = System.currentTimeMillis();
   this.running = true;
   this.currentTaskName = taskName;
 }
 /**
  * Stop the current task. The results are undefined if timing
  * methods are called without invoking at least one pair
  * {@link #start()} / {@link #stop()} methods.
  * @see #start()
  */
 public void stop() throws IllegalStateException {
   if (!this.running) {
     throw new IllegalStateException("Can"t stop StopWatch: it"s not running");
   }
   long lastTime = System.currentTimeMillis() - this.startTimeMillis;
   this.totalTimeMillis += lastTime;
   this.lastTaskInfo = new TaskInfo(this.currentTaskName, lastTime);
   if (this.keepTaskList) {
     this.taskList.add(lastTaskInfo);
   }
   ++this.taskCount;
   this.running = false;
   this.currentTaskName = null;
 }
 /**
  * Return whether the stop watch is currently running.
  */
 public boolean isRunning() {
   return this.running;
 }
 /**
  * Return the time taken by the last task.
  */
 public long getLastTaskTimeMillis() throws IllegalStateException {
   if (this.lastTaskInfo == null) {
     throw new IllegalStateException("No tests run: can"t get last interval");
   }
   return this.lastTaskInfo.getTimeMillis();
 }
 /**
  * Return the total time in milliseconds for all tasks.
  */
 public long getTotalTimeMillis() {
   return totalTimeMillis;
 }
 /**
  * Return the total time in seconds for all tasks.
  */
 public double getTotalTimeSeconds() {
   return totalTimeMillis / 1000.0;
 }
 /**
  * Return the number of tasks timed.
  */
 public int getTaskCount() {
   return taskCount;
 }
 /**
  * Return an array of the data for tasks performed.
  */
 public TaskInfo[] getTaskInfo() {
   if (!this.keepTaskList) {
     throw new UnsupportedOperationException("Task info is not being kept!");
   }
   return (TaskInfo[]) this.taskList.toArray(new TaskInfo[this.taskList.size()]);
 }
 /**
  * Return a short description of the total running time.
  */
 public String shortSummary() {
   return "StopWatch "" + this.id + "": running time (millis) = " + getTotalTimeMillis();
 }
 /**
  * Return a string with a table describing all tasks performed.
  * For custom reporting, call getTaskInfo() and use the task info directly.
  */
 public String prettyPrint() {
   StringBuffer sb = new StringBuffer(shortSummary());
   sb.append("\n");
   if (!this.keepTaskList) {
     sb.append("No task info kept");
   }
   else {
     TaskInfo[] tasks = getTaskInfo();
     sb.append("-----------------------------------------\n");
     sb.append("ms     %     Task name\n");
     sb.append("-----------------------------------------\n");
     NumberFormat nf = NumberFormat.getNumberInstance();
     nf.setMinimumIntegerDigits(5);
     nf.setGroupingUsed(false);
     NumberFormat pf = NumberFormat.getPercentInstance();
     pf.setMinimumIntegerDigits(3);
     pf.setGroupingUsed(false);
     for (int i = 0; i < tasks.length; i++) {
       sb.append(nf.format(tasks[i].getTimeMillis()) + "  ");
       sb.append(pf.format(tasks[i].getTimeSeconds() / getTotalTimeSeconds()) + "  ");
       sb.append(tasks[i].getTaskName() + "\n");
     }
   }
   return sb.toString();
 }
 /**
  * Return an informative string describing all tasks performed
  * For custom reporting, call getTaskInfo() and use the task info directly.
  */
 public String toString() {
   StringBuffer sb = new StringBuffer(shortSummary());
   if (this.keepTaskList) {
     TaskInfo[] tasks = getTaskInfo();
     for (int i = 0; i < tasks.length; i++) {
       sb.append("; [" + tasks[i].getTaskName() + "] took " + tasks[i].getTimeMillis());
       long percent = Math.round((100.0 * tasks[i].getTimeSeconds()) / getTotalTimeSeconds());
       sb.append(" = " + percent + "%");
     }
   }
   else {
     sb.append("; no task info kept");
   }
   return sb.toString();
 }
 /**
  * Inner class to hold data about one task executed within the stop watch.
  */
 public static class TaskInfo {
   private final String taskName;
   private final long timeMillis;
   private TaskInfo(String taskName, long timeMillis) {
     this.taskName = taskName;
     this.timeMillis = timeMillis;
   }
   /**
    * Return the name of this task.
    */
   public String getTaskName() {
     return taskName;
   }
   /**
    * Return the time in milliseconds this task took.
    */
   public long getTimeMillis() {
     return timeMillis;
   }
   /**
    * Return the time in seconds this task took.
    */
   public double getTimeSeconds() {
     return timeMillis / 1000.0;
   }
 }

}</source>





Some simple stop watch.

   <source lang="java">

/*

* Copyright 2000,2005 wingS development team.
*
* This file is part of wingS (http://wingsframework.org).
*
* wingS is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* Please see COPYING for the complete licence.
*/

import java.text.MessageFormat; import java.util.ArrayList; import java.util.Iterator; /*

* Ein Klasse, die Zeitmessungen aufnimmt und diese in Relation zueineander
* setzt. Zum Start der Zeitmessung Methode start kurzer Beschreibung was
* gemessen wird als Parameter aufrufen. Das Ende der Zeitmessung wird durch
* stop angezeigt. Es kann nur eine Zeitmessung gleichzeitig stattfinden. Die
* Ausgabe ist nicht sortiert, gibt aber die relativen Unterschiede in der
* Dauer der einzelnen Messungen an. Die Messung mit der laengsten Dauer ist
* der Referenzwert (1.0).
*/

/**

* Some simple stop watch. It allows to measure multiple time periods
* and prints them. Usage: call start(comment) and stop() for
* each period of time.
*
* @author 
*/

public class TimeMeasure {

   protected final static double RESOLUTION = 100.0;
   /**
    * List of measurements.
    */
   protected final ArrayList measures;
   /**
    * Message formatter
    */
   protected final MessageFormat formatter;
   /**
    * the current time measurement.
    */
   protected Measure current;
   /**
    * Simple TimeMesaure with default format.
    */
   public TimeMeasure() {
       this(new MessageFormat("{0}\t: {1}\t {2}x\n"));
   }
   /**
    * A new TimeMeasure which reports in a specific format. The
    * format is a standard MessageFormat with the following variables:
*
    *
  • {0} the measurement comment
  • *
  • {1} the time it took
  • *
  • {2} how many times this is faster than the * slowest measurement
  • *
    */
   public TimeMeasure(MessageFormat formatter) {
       this.measures = new ArrayList();
       this.formatter = formatter;
   }
   /**
    * Reset of all Measurements.
    */
   public void reset() {
       measures.clear();
   }
   /*
    * Startet eine neue Messsung.
    * @param comment  Die Beschreibung der Messung.
    */
   public void start(String comment) {
       current = new Measure(comment);
   }
   /*
    * Startet eine neue Messsung.
    * @param comment  Die Beschreibung der Messung.
   public Object generate(String comment) {
       current = new Measure();
       actual.rument = comment;
       measures.add(actual);
       return actual;
   }
    */
   /*
    * Addiert eine Messsung zu einer bestehenden.
    * @param comment  Die Beschreibung der Messung.
   public void addToMeasure(Object measure) {
       int index = measures.indexOf(measure);
       if ( index<0 ) {
           System.err.println("Measure does not exists " + measure);
           actual = null;
           return;
       }
       actual = (Measure)measures.get(index);
       measures.remove(index);
       actual.start = System.currentTimeMillis();
   }
    */
   /**
    * stop current time measurement and store it.
    */
   public void stop() {
       if (current != null) {
           current.stop();
           measures.add(current);
           current = null;
       }
   }
   /**
    * determines the time duration of the longest or shortest time interval.
    *
    * @param findShortest boolean "true", if we are looking for the shortest
    *                     time interval; "false" if we are looking for the
    *                     longest.
    */
   private long findReferenceValue(boolean findShortest) {
       long result = findShortest ? Long.MAX_VALUE : -1;
       Iterator it = measures.iterator();
       while (it.hasNext()) {
           Measure m = (Measure) it.next();
           result = (findShortest
                   ? Math.min(result, m.getDuration())
                   : Math.max(result, m.getDuration()));
       }
       return result;
   }
   public String print() {
       return print(false);
   }
   /**
    * creates a formatted output (using the MessageFormat) of all
    * results. The output is sorted in the in the sequence the time
    * measurements took place.
    * Writes the relative time to either the shortest or the longest
    * time interval.
    *
    * @param shortestIsReference boolean true, if the shortest time interval
    *                            is the reference value (1.0). False, if the
    *                            longest is the reference.
    */
   public String print(boolean shortestIsReference) {
       StringBuilder result = new StringBuilder();
       long reference = findReferenceValue(shortestIsReference);
       Iterator it = measures.iterator();
       while (it.hasNext()) {
           Measure m = (Measure) it.next();
           String factor = " -- ";
           long duration = m.getDuration();
           if (reference > 0) {
               long tmp = (long) ((duration * RESOLUTION) / reference);
               factor = String.valueOf(tmp / RESOLUTION);
           }
           Object[] args = {m.getComment(), (duration + "ms"), factor};
           result.append(formatter.format(args));
       }
       return result.toString();
   }
   public String toString() {
       return print();
   }
   /**
    * A class to store one period of time.
    */
   private final static class Measure {
       /**
        * start time.
        */
       private final long start;
       /**
        * stop time.
        */
       private long stop;
       /**
        * Die Gesamtdauer der Messung
        */
       private long duration;
       /**
        * Description.
        */
       private String comment;
       public Measure(String comment) {
           start = System.currentTimeMillis();
           this.rument = comment;
       }
       public void stop() {
           stop = System.currentTimeMillis();
           duration = stop - start;
       }
       public long getDuration() { return duration; }
       public String getComment() { return comment; }
   }

}</source>





Stop Watch

   <source lang="java">

import java.io.PrintWriter; /**

* Prints time durations; used for development purposes only.
* 
* No threads or system resources are harmed in the making of a stop watch. A
* stop watch simply remembers the start time (and elapsed time when paused) and
* prints the total "running" time when either {@link #mark} or
* {@link #stop} is called.
* 
* {@link #stop} doesn"t really stop anything. You can call stop as many times
* as you like and it will print the time elapsed since start. It would be easy
* to change this behavior, but I haven"t needed to.
* 
* @author Jim Menard, 
*/

public class StopWatch {

 protected String name;
 protected long t0;
 protected long elapsedTime;
 protected PrintWriter out;
 public StopWatch() {
   this(null, null);
 }
 public StopWatch(String name) {
   this(name, null);
 }
 public StopWatch(PrintWriter out) {
   this(null, out);
 }
 public StopWatch(String name, PrintWriter out) {
   this.name = name;
   if (out == null)
     this.out = new PrintWriter(System.err);
   else
     this.out = out;
   elapsedTime = -1L; // So we can tell if we are ever started
 }
 /**
  * Remembers the current time and prints a message.
  */
 public void start() {
   start(true);
 }
 /**
  * Remembers the current time and prints a message if requested.
  * 
  * @param printStarting
  *          if true and this stop watch has a name, print a
  *          message
  */
 public void start(boolean printStarting) {
   if (t0 != 0)
     System.err.println("(warning: StopWatch already started; resetting)");
   if (printStarting && name != null)
     System.err.println("starting " + name);
   elapsedTime = 0;
   t0 = System.currentTimeMillis();
 }
 /**
  * Pauses the stop watch.
  */
 public void pause() {
   long now = System.currentTimeMillis();
   elapsedTime += now - t0;
   t0 = 0;
 }
 /**
  * Resumes the stop watch.
  */
 public void resume() {
   t0 = System.currentTimeMillis();
 }
 /**
  * Prints the current elapsed time without stopping.
  */
 public void mark() {
   stop(null, true);
 }
 /**
  * Prints the current elapsed time without stopping, along with the stop watch
  * name if printMark is true.
  * 
  * @param printMark
  *          if true, the stop watch name will be printed
  */
 public void mark(boolean printMark) {
   stop(null, printMark);
 }
 /**
  * Prints the current elapsed time without stopping, along with the stop watch
  * name and msg.
  * 
  * @param msg
  *          a message to print
  */
 public void mark(String msg) {
   stop(msg, true);
 }
 /**
  * Prints the current elapsed time without stopping, along with, along with
  * the stop watch name if printMark is true and the
  * msg if it"s not null.
  * 
  * @param msg
  *          a message to print
  * @param printMark
  *          if true, the stop watch name will be printed
  */
 public void mark(String msg, boolean printMark) {
   stop(msg, printMark);
 }
 /**
  * Stops the stop watch and prints the name of this stop watch and the current
  * elapsed time.
  */
 public void stop() {
   stop(null, true);
 }
 /**
  * Stops the stop watch and prints the name of this stop watch, msg
  * if non-null, and the current elapsed time.
  * 
  * @param msg
  *          a message to print; may be null
  */
 public void stop(String msg) {
   stop(msg, true);
 }
 /**
  * Prints the current elapsed time, along with the stop watch name if
  * printMark is true and the msg if
  * it"s not null.
  * 
  * @param msg
  *          a message to print; may be null
  * @param printName
  *          if true, the stop watch name will be printed
  */
 public void stop(String msg, boolean printName) {
   long now = System.currentTimeMillis();
   if (elapsedTime == -1) {
     System.err.println("(StopWatch" + (name != null ? (" \"" + name + """) : "")
         + " was stopped without ever being started)");
     return;
   }
   long total = elapsedTime;
   if (t0 != 0)
     total += now - t0;
   String separator = null;
   if (printName && name != null) {
     System.err.print(name);
     separator = ": ";
   }
   if (msg != null) {
     if (separator != null)
       System.err.print(" ");
     System.err.print("(" + msg + ")");
     separator = ": ";
   }
   if (separator != null)
     System.err.print(separator);
   System.err.println("" + (total / 1000.0) + " seconds");
 }

}</source>





StopWatch provides a convenient API for timings.

   <source lang="java">

import java.util.Date; /*

* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License.  You may obtain a copy of the License at
* 
*      http://www.apache.org/licenses/LICENSE-2.0
* 
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/**

* 
* StopWatch provides a convenient API for timings.
* 
* 
* 
* To start the watch, call {@link #start()}. At this point you can:
* 
*
    *
  • {@link #split()} the watch to get the time whilst the watch continues in the background. {@link #unsplit()} will * remove the effect of the split. At this point, these three options are available again.
  • *
  • {@link #suspend()} the watch to pause it. {@link #resume()} allows the watch to continue. Any time between the * suspend and resume will not be counted in the total. At this point, these three options are available again.
  • *
  • {@link #stop()} the watch to complete the timing session.
  • *
* 
* 
* It is intended that the output methods {@link #toString()} and {@link #getTime()} should only be called after stop,
* split or suspend, however a suitable result will be returned at other points.
* 
* 
* 
* NOTE: As from v2.1, the methods protect against inappropriate calls. Thus you cannot now call stop before start,
* resume before suspend or unsplit before split.
* 
* 
* 
* 1. split(), suspend(), or stop() cannot be invoked twice
* 2. unsplit() may only be called if the watch has been split()
* 3. resume() may only be called if the watch has been suspend()
* 4. start() cannot be called twice without calling reset() * * * @author Stephen Colebourne * @since 2.0 * @version $Id: StopWatch.java 583608 2007-10-10 20:38:41Z ggregory $ */

public class StopWatch {

   // running states
   private static final int STATE_UNSTARTED = 0;
   private static final int STATE_RUNNING = 1;
   private static final int STATE_STOPPED = 2;
   private static final int STATE_SUSPENDED = 3;
   // split state
   private static final int STATE_UNSPLIT = 10;
   private static final int STATE_SPLIT = 11;
   /**
    * The current running state of the StopWatch.
    */
   private int runningState = STATE_UNSTARTED;
   /**
    * Whether the stopwatch has a split time recorded.
    */
   private int splitState = STATE_UNSPLIT;
   /**
    * The start time.
    */
   private long startTime = -1;
   /**
    * The stop time.
    */
   private long stopTime = -1;
   /**
    * 
    * Constructor.
    * 
    */
   public StopWatch() {
       super();
   }
   /**
    * 
    * Start the stopwatch.
    * 
    * 
    * 
    * This method starts a new timing session, clearing any previous values.
    * 
    * 
    * @throws IllegalStateException
    *             if the StopWatch is already running.
    */
   public void start() {
       if (this.runningState == STATE_STOPPED) {
           throw new IllegalStateException("Stopwatch must be reset before being restarted. ");
       }
       if (this.runningState != STATE_UNSTARTED) {
           throw new IllegalStateException("Stopwatch already started. ");
       }
       this.stopTime = -1;
       this.startTime = System.currentTimeMillis();
       this.runningState = STATE_RUNNING;
   }
   /**
    * 
    * Stop the stopwatch.
    * 
    * 
    * 
    * This method ends a new timing session, allowing the time to be retrieved.
    * 
    * 
    * @throws IllegalStateException
    *             if the StopWatch is not running.
    */
   public void stop() {
       if (this.runningState != STATE_RUNNING && this.runningState != STATE_SUSPENDED) {
           throw new IllegalStateException("Stopwatch is not running. ");
       }
       if (this.runningState == STATE_RUNNING) {
           this.stopTime = System.currentTimeMillis();
       }
       this.runningState = STATE_STOPPED;
   }
   /**
    * 
    * Resets the stopwatch. Stops it if need be.
    * 
    * 
    * 
    * This method clears the internal values to allow the object to be reused.
    * 
    */
   public void reset() {
       this.runningState = STATE_UNSTARTED;
       this.splitState = STATE_UNSPLIT;
       this.startTime = -1;
       this.stopTime = -1;
   }
   /**
    * 
    * Split the time.
    * 
    * 
    * 
    * This method sets the stop time of the watch to allow a time to be extracted. The start time is unaffected,
    * enabling {@link #unsplit()} to continue the timing from the original start point.
    * 
    * 
    * @throws IllegalStateException
    *             if the StopWatch is not running.
    */
   public void split() {
       if (this.runningState != STATE_RUNNING) {
           throw new IllegalStateException("Stopwatch is not running. ");
       }
       this.stopTime = System.currentTimeMillis();
       this.splitState = STATE_SPLIT;
   }
   /**
    * 
    * Remove a split.
    * 
    * 
    * 
    * This method clears the stop time. The start time is unaffected, enabling timing from the original start point to
    * continue.
    * 
    * 
    * @throws IllegalStateException
    *             if the StopWatch has not been split.
    */
   public void unsplit() {
       if (this.splitState != STATE_SPLIT) {
           throw new IllegalStateException("Stopwatch has not been split. ");
       }
       this.stopTime = -1;
       this.splitState = STATE_UNSPLIT;
   }
   /**
    * 
    * Suspend the stopwatch for later resumption.
    * 
    * 
    * 
    * This method suspends the watch until it is resumed. The watch will not include time between the suspend and
    * resume calls in the total time.
    * 
    * 
    * @throws IllegalStateException
    *             if the StopWatch is not currently running.
    */
   public void suspend() {
       if (this.runningState != STATE_RUNNING) {
           throw new IllegalStateException("Stopwatch must be running to suspend. ");
       }
       this.stopTime = System.currentTimeMillis();
       this.runningState = STATE_SUSPENDED;
   }
   /**
    * 
    * Resume the stopwatch after a suspend.
    * 
    * 
    * 
    * This method resumes the watch after it was suspended. The watch will not include time between the suspend and
    * resume calls in the total time.
    * 
    * 
    * @throws IllegalStateException
    *             if the StopWatch has not been suspended.
    */
   public void resume() {
       if (this.runningState != STATE_SUSPENDED) {
           throw new IllegalStateException("Stopwatch must be suspended to resume. ");
       }
       this.startTime += (System.currentTimeMillis() - this.stopTime);
       this.stopTime = -1;
       this.runningState = STATE_RUNNING;
   }
   /**
    * 
    * Get the time on the stopwatch.
    * 
    * 
    * 
    * This is either the time between the start and the moment this method is called, or the amount of time between
    * start and stop.
    * 
    * 
    * @return the time in milliseconds
    */
   public long getTime() {
       if (this.runningState == STATE_STOPPED || this.runningState == STATE_SUSPENDED) {
           return this.stopTime - this.startTime;
       } else if (this.runningState == STATE_UNSTARTED) {
           return 0;
       } else if (this.runningState == STATE_RUNNING) {
           return System.currentTimeMillis() - this.startTime;
       }
       throw new RuntimeException("Illegal running state has occured. ");
   }
   /**
    * 
    * Get the split time on the stopwatch.
    * 
    * 
    * 
    * This is the time between start and latest split.
    * 
    * 
    * @return the split time in milliseconds
    * 
    * @throws IllegalStateException
    *             if the StopWatch has not yet been split.
    * @since 2.1
    */
   public long getSplitTime() {
       if (this.splitState != STATE_SPLIT) {
           throw new IllegalStateException("Stopwatch must be split to get the split time. ");
       }
       return this.stopTime - this.startTime;
   }
   /**
    * Returns the time this stopwatch was started.
    * 
    * @return the time this stopwatch was started
    * @throws IllegalStateException
    *             if this StopWatch has not been started
    * @since 2.4
    */
   public long getStartTime() {
       if (this.runningState == STATE_UNSTARTED) {
           throw new IllegalStateException("Stopwatch has not been started");
       }
       return this.startTime;
   }
   /**
    * 
    * Gets a summary of the time that the stopwatch recorded as a string.
    * 
    * 
    * 
    * The format used is ISO8601-like, hours:minutes:seconds.milliseconds.
    * 
    * 
    * @return the time as a String
    */
   public String toString() {
       return new Date(getTime()).toString();
   }
   /**
    * 
    * Gets a summary of the split time that the stopwatch recorded as a string.
    * 
    * 
    * 
    * The format used is ISO8601-like, hours:minutes:seconds.milliseconds.
    * 
    * 
    * @return the split time as a String
    * @since 2.1
    */
   public String toSplitString() {
       return new Date(getSplitTime()).toString();
   }

}</source>