home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1995 November / PCWK1195.iso / inne / win95 / sieciowe / hotja32.lzh / hotjava / classsrc / java / lang / thread.java < prev    next >
Text File  |  1995-08-11  |  12KB  |  408 lines

  1. /*
  2.  * @(#)Thread.java    1.27 95/05/12  
  3.  *
  4.  * Copyright (c) 1994 Sun Microsystems, Inc. All Rights Reserved.
  5.  *
  6.  * Permission to use, copy, modify, and distribute this software
  7.  * and its documentation for NON-COMMERCIAL purposes and without
  8.  * fee is hereby granted provided that this copyright notice
  9.  * appears in all copies. Please refer to the file "copyright.html"
  10.  * for further important copyright and licensing information.
  11.  *
  12.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
  13.  * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
  14.  * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  15.  * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
  16.  * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
  17.  * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
  18.  */
  19.  
  20. package java.lang;
  21.  
  22. /**
  23.  * Thread objects are the basis for multi-threaded programming.  To
  24.  * create a new thread of execution, declare a new class which is a
  25.  * subclass of Thread.  Override the run() method with a method whose
  26.  * body is the code you want to execute in the thread.  Then create
  27.  * an instance of the class and call the start() method to create the
  28.  * thread and run the run method. For example:<p>
  29.  * <pre>
  30.  *    class PrimeThread extends Thread {
  31.  *        public void run() {
  32.  *        // compute primes...
  33.  *        }
  34.  *    }
  35.  * </pre>
  36.  * To start this thread you need to do the following:
  37.  * <pre>
  38.  *    PrimeThread p = new PrimeThread();
  39.  *    p.start();
  40.  *    ...
  41.  * </pre>
  42.  * Another way to create a thread is by using the Runnable interface.
  43.  * This way any object that implements the Runnable interface can be
  44.  * run in a thread. For example:
  45.  * <pre>
  46.  *    class Primes Implements Runnable {
  47.  *        public void run() {
  48.  *        // compute primes...
  49.  *        }
  50.  *    }
  51.  * </pre>
  52.  * To start this thread you need to do the following:
  53.  * <pre>
  54.  *    Primes p = new Primes();
  55.  *    new Thread(p).start();
  56.  *    ...
  57.  * </pre>
  58.  * The interpreter runs until all threads that are not deamon threads
  59.  * have died. A thread dies when its run method returns, or when the
  60.  * stop method is called.<p>
  61.  * When a new thread is created, it inherits the priority and the
  62.  * daemon flag from its parent (ie: the thread that created it).
  63.  * @version     1.27, 12 May 1995
  64.  */
  65. public
  66. class Thread implements Runnable {
  67.     private char    name[];
  68.     private int         priority;
  69.     private Thread    threadQ;
  70.     private int     PrivateInfo;
  71.     private int        eetop;
  72.  
  73.     /* Whether or not to single_step this thread. */
  74.     private boolean    single_step;
  75.  
  76.     /* Whether or not the thread is a daemon thread. */
  77.     private boolean    daemon = false;
  78.  
  79.     /* Set to true if thread is asked to exit before it starts running */
  80.     private boolean    stillborn = false;
  81.  
  82.     /* What will be run. */
  83.     private Runnable target;
  84.  
  85.     /* The system queue of threads is linked through activeThreadQueue. */
  86.     private static Thread activeThreadQ;
  87.  
  88.     /* For autonumbering anonymous threads. */
  89.     private static int threadInitNumber;
  90.     private synchronized int nextThreadNum() {
  91.     return threadInitNumber++;
  92.     }
  93.  
  94.     /* Does this do anything? */
  95.     private static int    SingleSteppingThreads = 0;
  96.  
  97.  
  98.     /**
  99.      * The minimum priority that a Thread can have.
  100.      */
  101.     public final static int MIN_PRIORITY = 1;
  102.  
  103.     /**
  104.      * The default priority that is assigned to a Thread.
  105.      */
  106.     public final static int NORM_PRIORITY = 5;
  107.  
  108.     /**
  109.      * The maximum priority that a Thread can have.
  110.      */
  111.     public final static int MAX_PRIORITY = 10;
  112.  
  113.     /**
  114.      * Returns a reference to the currently executing thread object.
  115.      * @returns the current thread
  116.      */
  117.     public static native Thread currentThread();
  118.  
  119.     /**
  120.      * Causes the currently executing thread object to yield.
  121.      * (i.e., if there are other runnable threads they will be
  122.      * scheduled next).
  123.      */
  124.     public static native void yield();
  125.  
  126.     /**
  127.      * Causes the currently executing thread to sleep for the specified
  128.      * number of milliseconds.
  129.      * @params millis    the length of time to sleep in milliseconds
  130.      */
  131.     public static native void sleep(int millis);
  132.  
  133.     /**
  134.      * Constructs a new thread. Threads created this way must have
  135.      * overridden their run() method to actually do anything.
  136.      */
  137.     public Thread() {
  138.     Thread parent = currentThread();
  139.     this.name = ("Thread-" + nextThreadNum()).toCharArray();
  140.     this.daemon = parent.isDaemon();
  141.     this.priority = parent.getPriority();
  142.     setThreadPriority(priority);
  143.     }
  144.  
  145.     /**
  146.      * Constructs a new thread that applies the run method to
  147.      * the specified target.
  148.      * @param target    the object who's run method is called
  149.      */
  150.     public Thread(Runnable target) {
  151.     Thread parent = currentThread();
  152.     this.name = ("Thread-" + nextThreadNum()).toCharArray();
  153.     this.daemon = parent.isDaemon();
  154.     this.priority = parent.getPriority();
  155.     this.target = target;
  156.     setThreadPriority(priority);
  157.     }
  158.  
  159.     /**
  160.      * Constructs a new thread with the specified name.
  161.      * @param name    the name of the new thread
  162.      */
  163.     public Thread(String name) {
  164.     Thread parent = currentThread();
  165.     this.name = name.toCharArray();
  166.     this.daemon = parent.isDaemon();
  167.     this.priority = parent.getPriority();
  168.     setThreadPriority(priority);
  169.     }
  170.  
  171.     /**
  172.      * Constructs a new thread with the specified name and applies
  173.      * the run() method on the specified target.
  174.      * @param target    the object whose run method is called
  175.      * @param name    the name of the new thread
  176.      */
  177.     public Thread(Runnable target, String name) {
  178.     Thread parent = currentThread();
  179.     this.name = name.toCharArray();
  180.     this.daemon = parent.isDaemon();
  181.     this.priority = parent.getPriority();
  182.     this.target = target;
  183.     setThreadPriority(priority);
  184.     }
  185.  
  186.     /**
  187.      * Starts a thread. This will cause the run() method to
  188.      * be called. This method will return immediately.
  189.      * @exception IllegalStateException The thread was already started
  190.      * @see Thread#run
  191.      * @see Thread#stop
  192.      */
  193.     public synchronized native void start();
  194.  
  195.     /**
  196.      * Post an object to another thread, to be thrown when it
  197.      * resumes.  If the object being posted is an instance of class
  198.      * Exception the stack trace of the thread being posted to will
  199.      * be filled in the instance.  This routine is used by
  200.      * Thread.stop() to asynchronously terminate threads.
  201.      * @param instance to post
  202.      * @exception IllegalStateException If the target thread is not started
  203.      */
  204.     public native void postException(Object exception);
  205.  
  206.     /**
  207.      * The body of the thread. This method is called after
  208.      * the thread is started. You must either override this
  209.      * method by subclassing class Thread, or you must create
  210.      * the thread with a target.
  211.      * @see Thread#start
  212.      * @see Thread#stop
  213.      */
  214.     public void run() {
  215.     if (target != null) {
  216.         target.run();
  217.     }
  218.     }
  219.  
  220.     /** 
  221.      * Stops a thread by tossing an object.  By default this
  222.      * routine tosses a new instance of ThreadDeath to the target
  223.      * thread.  ThreadDeath is not actually a subclass of Exception,
  224.      * but is a subclass of Object.  Users should not normally try
  225.      * to catch ThreaDeath unless they must do some extraordinary
  226.      * cleanup operation.  If ThreadDeath is caught it is important
  227.      * to rethrow the object so that the thread will actually die.
  228.      * The top-level error handler will not print out a message if
  229.      * ThreadDeath falls through.
  230.      *
  231.      * The essential difference between this routine and
  232.      * postException() is that if the target thread has not yet
  233.      * started to run it will be killed imediately without trying to
  234.      * post the object instance as an error.
  235.      *
  236.      * @exception IllegalStateException If the thread is not started 
  237.      * @see Thread#start 
  238.      * @see Thread#run
  239.      */
  240.     // public synchronized native void stop();
  241.     public synchronized void stop() {
  242.     stop(new ThreadDeath());
  243.     }
  244.  
  245.     /**
  246.      * Stops a thread by tossing an object.  Normally users should
  247.      * just call Thread.Stop() with no argument.  In some
  248.      * exceptional circumstances Used by Thread.Stop() to kill
  249.      * anothe is tossed, "ThreadDeath", is not actually a subclass
  250.      * of Exception, but is a subclass of Object.  The essential
  251.      * difference between this routine and postException() is that
  252.      * if the target thread has not yet started to run it will be
  253.      * killed imediately without trying to post the object instance
  254.      * as an error.
  255.      * @exception IllegalStateException If the thread is not started 
  256.      * @see Thread#start 
  257.      * @see Thread#run 
  258.      */
  259.     public synchronized native void stop(Object o);
  260.  
  261.     /**
  262.      * Returns a boolean indicating if the thread is active.
  263.      * @return     a boolean indicating whether the thread has been started
  264.      */
  265.     public native boolean isAlive();
  266.  
  267.     /**
  268.      * Suspends the thread execution.
  269.      * @exception IllegalStateException The thread is not active.
  270.      */
  271.     public native void suspend();
  272.  
  273.     /**
  274.      * Resumes the thread execution.
  275.      * @exception IllegalStateException The thread is not active.
  276.      */
  277.     public native void resume();
  278.  
  279.     /**
  280.      * Sets the thread's priority.
  281.      * @exception IllegalArgumentException The priority is not within the
  282.      *        range MIN_PRIORITY, MAX_PRIORITY
  283.      * @see Thread#MIN_PRIORITY
  284.      * @see Thread#MAX_PRIORITY
  285.      * @see Thread#getPriority
  286.      */
  287.     public void setPriority(int newPriority) {
  288.     if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) {
  289.         throw new IllegalArgumentException();
  290.     }
  291.     setThreadPriority(priority = newPriority);
  292.     }
  293.  
  294.     public native void setThreadPriority(int newPriority);
  295.  
  296.     /**
  297.      * Returns the thread's priority.
  298.      * @return the priority of the thread
  299.      * @see Thread#setPriority
  300.      */
  301.     public int getPriority() {
  302.     return priority;
  303.     }
  304.  
  305.     /**
  306.      * Sets the thread's name.
  307.      * @param name    the new name of the thread
  308.      * @see Thread#getName
  309.      */
  310.     public void setName(String name) {
  311.     this.name = name.toCharArray();
  312.     }
  313.  
  314.     /**
  315.      * Returns the thread's name.
  316.      * @return     the name of the thread
  317.      * @see Thread#setName
  318.      */
  319.     public String getName() {
  320.     return String.valueOf(name);
  321.     }
  322.  
  323.     /**
  324.      * Returns the current number of active threads.
  325.      * @return integer count of active threads 
  326.      */
  327.     public static native int activeCount();
  328.  
  329.     /**
  330.      * Copies references to every active thread into an array.
  331.      * @return number of Threads put into the array
  332.      */
  333.     public static native int enumerate(Thread tarray[]);
  334.  
  335.     /**
  336.      * Returns the number of stack frames in this thread. The thread
  337.      * must be suspended when this method is called.
  338.      * @exception    IllegalStateException The thread is not suspended
  339.      */
  340.     public native int countStackFrames();
  341.  
  342.     /**
  343.      * Waits for this thread to die.  A timeout in milliseconds can
  344.      * be specified.  A timeout of 0 milliseconds means to wait
  345.      * forever.
  346.      * @param millis    the time to wait in milliseconds
  347.      */
  348.     public synchronized void join(int millis) {
  349.     int base = System.nowMillis();
  350.     int now = 0;
  351.  
  352.     if (millis == 0) {
  353.         while (isAlive()) {
  354.         wait(0);
  355.         }
  356.     } else {
  357.         while (isAlive()) {
  358.         int delay = millis - now;
  359.         if (delay <= 0) {
  360.             break;
  361.         }
  362.         wait(delay);
  363.         now = System.nowMillis() - base;
  364.         }
  365.     }
  366.     }
  367.  
  368.     /**
  369.      * Waits forever for this thread to die.
  370.      */
  371.     public void join() {
  372.     join(0);
  373.     }
  374.  
  375.     /**
  376.      * A debugging procedure to print a stack trace for the
  377.      * current thread.
  378.      * @see Exception#printStackTrace
  379.      */
  380.     public static void dumpStack() {
  381.     new Exception("Stack trace").printStackTrace();
  382.     }
  383.  
  384.     /**
  385.      * Marks this thread as a daemon thread or a user thread.
  386.      * When there are only daemon threads left running in the
  387.      * system, Java exits.
  388.      * @param on    determines whether the thread will be a deamon thread
  389.      * @exception IllegalStateException The thread is active
  390.      * @see Thread#isDaemon
  391.      */
  392.     public void setDaemon(boolean on) {
  393.     if (isAlive()) {
  394.         throw new IllegalStateException();
  395.     }
  396.     daemon = on;
  397.     }
  398.  
  399.     /**
  400.      * Returns the deamon flag of the thread.
  401.      * @return    a boolean indicating wheter the thread is a deamon thread
  402.      * @see Thread#setDaemon
  403.      */
  404.     public boolean isDaemon() {
  405.     return daemon;
  406.     }
  407. }
  408.