home *** CD-ROM | disk | FTP | other *** search
/ Java Programmer's Toolkit / Java Programmer's Toolkit.iso / src / java / lang / thread~1.jav < prev    next >
Encoding:
Text File  |  1996-01-12  |  16.7 KB  |  575 lines

  1. /*
  2.  * @(#)Thread.java    1.47 95/12/03  
  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.  * A Thread is a single sequential flow of control within a process. This simply means
  24.  * that while executing within a program, each thread has a beginning, a sequence, a 
  25.  * point of execution occurring at any time during runtime of the thread and of course, an ending. 
  26.  * Thread objects are the basis for multi-threaded programming.  Multi-threaded programming
  27.  * allows a single program to conduct concurrently running threads that perform different tasks.
  28.  * <p>
  29.  * To create a new thread of execution, declare a new class which is a
  30.  * subclass of Thread and then override the run() method with code that you
  31.  * want executed in this Thread.  An instance of the Thread subclass should be created next
  32.  * with a call to the start() method following the instance.  The start() method will create the 
  33.  * thread and execute the run() method. 
  34.  * For example:<p>
  35.  * <pre>
  36.  *    class PrimeThread extends Thread {
  37.  *        public void run() {
  38.  *        // compute primes...
  39.  *        }
  40.  *    }
  41.  * </pre>
  42.  * To start this thread you need to do the following:
  43.  * <pre>
  44.  *    PrimeThread p = new PrimeThread();
  45.  *    p.start();
  46.  *    ...
  47.  * </pre>
  48.  * Another way to create a thread is by using the Runnable interface.
  49.  * This way any object that implements the Runnable interface can be
  50.  * run in a thread. For example:
  51.  * <pre>
  52.  *    class Primes implements Runnable {
  53.  *        public void run() {
  54.  *        // compute primes...
  55.  *        }
  56.  *    }
  57.  * </pre>
  58.  * To start this thread you need to do the following:
  59.  * <pre>
  60.  *    Primes p = new Primes();
  61.  *    new Thread(p).start();
  62.  *    ...
  63.  * </pre>
  64.  * The virtual machine runs until all Threads that are not daemon Threads
  65.  * have died. A Thread dies when its run() method returns, or when the
  66.  * stop() method is called.
  67.  * <p>
  68.  * When a new Thread is created, it inherits the priority and the
  69.  * daemon flag from its parent (i.e.: the Thread that created it).
  70.  * @see Runnable
  71.  * @version     1.47, 12/03/95
  72.  */
  73. public
  74. class Thread implements Runnable {
  75.     private char    name[];
  76.     private int         priority;
  77.     private Thread    threadQ;
  78.     private int     PrivateInfo;
  79.     private int        eetop;
  80.  
  81.     /* Whether or not to single_step this thread. */
  82.     private boolean    single_step;
  83.  
  84.     /* Whether or not the thread is a daemon thread. */
  85.     private boolean    daemon = false;
  86.  
  87.     /* Whether or not this thread was asked to exit before it runs.*/
  88.     private boolean    stillborn = false;
  89.  
  90.     /* What will be run. */
  91.     private Runnable target;
  92.  
  93.     /* The system queue of threads is linked through activeThreadQueue. */
  94.     private static Thread activeThreadQ;
  95.  
  96.     /* The group of this thread */
  97.     private ThreadGroup group;
  98.  
  99.     /* For autonumbering anonymous threads. */
  100.     private static int threadInitNumber;
  101.     private static synchronized int nextThreadNum() {
  102.     return threadInitNumber++;
  103.     }
  104.  
  105.     /**
  106.      * The minimum priority that a Thread can have.  The most minimal priority is equal to 1.      
  107.      */
  108.     public final static int MIN_PRIORITY = 1;
  109.  
  110.     /**
  111.      * The default priority that is assigned to a Thread.  The default priority is equal to 5.
  112.      */
  113.     public final static int NORM_PRIORITY = 5;
  114.  
  115.     /**
  116.      * The maximum priority that a Thread can have.  The maximal priority value a Thread can have is 10.
  117.      */
  118.     public final static int MAX_PRIORITY = 10;
  119.  
  120.     /**
  121.      * Returns a reference to the currently executing Thread object.
  122.      */
  123.     public static native Thread currentThread();
  124.  
  125.     /**
  126.      * Causes the currently executing Thread object to yield.
  127.      * If there are other runnable Threads they will be
  128.      * scheduled next.
  129.      */
  130.     public static native void yield();
  131.  
  132.     /**    
  133.      * Causes the currently executing Thread to sleep for the specified
  134.      * number of milliseconds.
  135.      * @param millis  the length of time to sleep in milliseconds
  136.      * @exception InterruptedException 
  137.      *            Another thread has interrupted this thread.      */
  138.     public static native void sleep(long millis) throws InterruptedException;
  139.  
  140.     /**
  141.      * Sleep, in milliseconds and additional nanosecond.
  142.      * @param millis  the length of time to sleep in milliseconds
  143.      * @param nanos   0-999999 additional nanoseconds to sleep
  144.      * @exception InterruptedException 
  145.      *            Another thread has interrupted this thread. 
  146.      */
  147.     public static void sleep(long millis, int nanos) throws InterruptedException {
  148.     if (nanos > 500000)
  149.         millis++;
  150.     sleep(millis);
  151.     }
  152.  
  153.     /**
  154.      * Initialize a Thread.
  155.      * @param g the Thread group
  156.      * @param target the object whose run() method gets called
  157.      * @param name the name of the new Thread
  158.      */
  159.     private void init(ThreadGroup g, Runnable target, String name){
  160.     Thread parent = currentThread();
  161.     if (g == null) {
  162.         g = parent.getThreadGroup();
  163.     } else {
  164.         g.checkAccess();
  165.     }
  166.     this.group = g;
  167.     this.daemon = parent.isDaemon();
  168.     this.priority = parent.getPriority();
  169.     this.name = name.toCharArray();
  170.     this.target = target;
  171.     setPriority0(priority);
  172.     g.add(this);
  173.     }
  174.  
  175.     /**
  176.      * Constructs a new Thread. Threads created this way must have
  177.      * overridden their run() method to actually do anything.  An example
  178.      * illustrating this method being used is shown.
  179.      * <p><pre>
  180.      * import java.lang.*; 
  181.      * <p>
  182.      * class plain01 implements Runnable {
  183.      *   String name; 
  184.      *   plain01() {
  185.      *     name = null;
  186.      *   }
  187.      *   plain01(String s) {
  188.      *     name = s;
  189.      *   }
  190.      *   public void run() {
  191.      *     if (name == null)
  192.      *       System.out.println("A new thread created");
  193.      *     else
  194.      *       System.out.println("A new thread with name " + name + " created");
  195.      *   }
  196.      * }<p>
  197.      * class threadtest01 {
  198.      *   public static void main(String args[] ) {
  199.      *     int failed = 0 ;
  200.      * <p>
  201.      * <b>   Thread t1 = new Thread();</b>  
  202.      *     if(t1 != null) {
  203.      *       System.out.println("new Thread() succeed");
  204.      *     } else {
  205.      *        System.out.println("new Thread() failed"); 
  206.      *        failed++; 
  207.      *     } </pre>
  208.      * } <p>
  209.      */
  210.     public Thread() {
  211.     init(null, null, "Thread-" + nextThreadNum());
  212.     }
  213.  
  214.     /**
  215.      * Constructs a new Thread which applies the run() method of
  216.      * the specified target.  
  217.      * @param target    the object whose run() method is called
  218.      */
  219.     public Thread(Runnable target) {
  220.     init(null, target, "Thread-" + nextThreadNum());
  221.     }
  222.  
  223.     /**
  224.      * Constructs a new Thread in the specified Thread group that applies the run() method of
  225.      * the specified target. 
  226.      * @param group the Thread group
  227.      * @param target    the object whose run() method is called
  228.      */
  229.     public Thread(ThreadGroup group, Runnable target) {
  230.     init(group, target, "Thread-" + nextThreadNum());
  231.     }
  232.  
  233.     /**
  234.      * Constructs a new Thread with the specified name.  
  235.      * @param name    the name of the new Thread
  236.      */
  237.     public Thread(String name) {
  238.     init(null, null, name);
  239.     }
  240.  
  241.     /**
  242.      * Constructs a new Thread in the specified Thread group with the specified name.
  243.      * @param group the Thread group
  244.      * @param name    the name of the new Thread
  245.      */
  246.     public Thread(ThreadGroup group, String name) {
  247.     init(group, null, name);
  248.     }
  249.  
  250.     /**
  251.      * Constructs a new Thread with the specified name and applies
  252.      * the run() method of the specified target.  
  253.      * @param target    the object whose run() method is called
  254.      * @param name    the name of the new Thread
  255.      */
  256.     public Thread(Runnable target, String name) {
  257.     init(null, target, name);
  258.     }
  259.     /**
  260.      * Constructs a new Thread in the specified Thread group with the specified name and
  261.      * applies the run() method of the specified target.
  262.      * @param group the Thread group
  263.      * @param target the object whose run() method is called
  264.      * @param name the name of the new Thread
  265.      */
  266.     public Thread(ThreadGroup group, Runnable target, String name) {
  267.     init(group, target, name);
  268.     }
  269.  
  270.     /**
  271.      * Starts this Thread. This will cause the run() method to
  272.      * be called. This method will return immediately.
  273.      * @exception IllegalThreadStateException If the thread was already started.
  274.      * @see Thread#run
  275.      * @see Thread#stop
  276.      */
  277.     public synchronized native void start();
  278.  
  279.     /**
  280.      * The actual body of this Thread. This method is called after
  281.      * the Thread is started. You must either override this
  282.      * method by subclassing class Thread, or you must create
  283.      * the Thread with a Runnable target.
  284.      * @see Thread#start
  285.      * @see Thread#stop
  286.      */
  287.     public void run() {
  288.     if (target != null) {
  289.         target.run();
  290.     }
  291.     }
  292.  
  293.     /**
  294.      * This method is called by the system to give a Thread
  295.      * a chance to clean up before it actually exits.
  296.      */
  297.     private void exit() {
  298.     if (group != null) {
  299.         group.remove(this);
  300.         group = null;
  301.     }
  302.     }
  303.  
  304.     /** 
  305.      * Stops a Thread by tossing an object.  By default this
  306.      * routine tosses a new instance of ThreadDeath to the target
  307.      * Thread.  ThreadDeath is not actually a subclass of Exception,
  308.      * but is a subclass of Object.  Users should not normally try
  309.      * to catch ThreadDeath unless they must do some extraordinary
  310.      * cleanup operation.  If ThreadDeath is caught it is important
  311.      * to rethrow the object so that the thread will actually die.
  312.      * The top-level error handler will not print out a message if
  313.      * ThreadDeath falls through.
  314.      *
  315.      * @see Thread#start 
  316.      * @see Thread#run
  317.      */
  318.     public final void stop() {
  319.     stop(new ThreadDeath());
  320.     }
  321.  
  322.     /**
  323.      * Stops a Thread by tossing an object.  Normally, users should
  324.      * just call the stop() method without any argument.  However, in some
  325.      * exceptional circumstances used by the stop() method to kill a Thread,
  326.      * another object is tossed. ThreadDeath, is not actually a subclass
  327.      * of Exception, but is a subclass of Throwable
  328.      * @param o the Throwable object to be thrown
  329.      * @see Thread#start 
  330.      * @see Thread#run 
  331.      */
  332.     public final synchronized void stop(Throwable o) {
  333.     checkAccess();
  334.     stop0(o);
  335.     }
  336.  
  337.     /**
  338.      * Send an interrupt to a thread.
  339.      */
  340.     public void interrupt() {
  341.     throw new NoSuchMethodError();
  342.     }
  343.  
  344.     /**
  345.      * Ask if you have been interrupted.
  346.      */
  347.     public static boolean interrupted() {
  348.     throw new NoSuchMethodError();
  349.     }
  350.  
  351.     /**
  352.      * Ask if another thread has been interrupted.
  353.      */
  354.     public boolean isInterrupted() {
  355.     throw new NoSuchMethodError();
  356.     }
  357.  
  358.     /**
  359.      * Destroy a thread, without any cleanup, i.e. just toss its state;
  360.      * any monitors it has locked remain locked.  A last resort.
  361.      */
  362.     public void destroy() {
  363.     throw new NoSuchMethodError();
  364.     }
  365.  
  366.     /**
  367.      * Returns a boolean indicating if the Thread is active.  Having an 
  368.      * active Thread means that the Thread has been started and has not
  369.      * been stopped.
  370.      */
  371.     public final native boolean isAlive();
  372.  
  373.     /**
  374.      * Suspends this Thread's execution.
  375.      */
  376.     public final void suspend() {
  377.     checkAccess();
  378.     suspend0();
  379.     }
  380.  
  381.     /**
  382.      * Resumes this Thread execution.  This method is only valid after suspend()
  383.      * has been invoked.
  384.      */
  385.     public final void resume() {
  386.     checkAccess();
  387.     resume0();
  388.     }
  389.  
  390.     /**
  391.      * Sets the Thread's priority.
  392.      * @exception IllegalArgumentException If the priority is not within the
  393.      *        range MIN_PRIORITY, MAX_PRIORITY.
  394.      * @see Thread#MIN_PRIORITY
  395.      * @see Thread#MAX_PRIORITY
  396.      * @see Thread#getPriority
  397.      */
  398.     public final void setPriority(int newPriority) {
  399.     checkAccess();
  400.     if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) {
  401.         throw new IllegalArgumentException();
  402.     }
  403.     if (newPriority > group.getMaxPriority()) {
  404.         newPriority = group.getMaxPriority();
  405.     }
  406.     setPriority0(priority = newPriority);
  407.     }
  408.  
  409.     /**
  410.      * Gets and returns the Thread's priority.
  411.      * @see Thread#setPriority
  412.      */
  413.     public final int getPriority() {
  414.     return priority;
  415.     }
  416.  
  417.     /**
  418.      * Sets the Thread's name.
  419.      * @param name    the new name of the Thread
  420.      * @see Thread#getName
  421.      */
  422.     public final void setName(String name) {
  423.     checkAccess();
  424.     this.name = name.toCharArray();
  425.     }
  426.  
  427.     /**
  428.      * Gets and returns this Thread's name.
  429.      * @see Thread#setName
  430.      */
  431.     public final String getName() {
  432.     return String.valueOf(name);
  433.     }
  434.  
  435.     /**
  436.      * Gets and returns this Thread group.
  437.      */
  438.     public final ThreadGroup getThreadGroup() {
  439.     return group;
  440.     }
  441.  
  442.  
  443.     /**
  444.      * Returns the current number of active Threads in this Thread group.
  445.      */
  446.     public static int activeCount() {
  447.     return currentThread().getThreadGroup().activeCount();
  448.     }
  449.  
  450.     /**
  451.      * Copies, into the specified array, references to every active Thread in this 
  452.      * Thread's group.
  453.      * @return the number of Threads put into the array.
  454.      */
  455.     public static int enumerate(Thread tarray[]) {
  456.     return currentThread().getThreadGroup().enumerate(tarray);
  457.     }
  458.  
  459.     /**
  460.      * Returns the number of stack frames in this Thread. The Thread
  461.      * must be suspended when this method is called.
  462.      * @exception    IllegalThreadStateException If the Thread is not suspended.
  463.      */
  464.     public native int countStackFrames();
  465.  
  466.     /**
  467.      * Waits for this Thread to die.  A timeout in milliseconds can
  468.      * be specified.  A timeout of 0 milliseconds means to wait
  469.      * forever.
  470.      * @param millis    the time to wait in milliseconds
  471.      * @exception InterruptedException 
  472.      *            Another thread has interrupted this thread. 
  473.      */
  474.     public final synchronized void join(long millis) throws InterruptedException {
  475.     long base = System.currentTimeMillis();
  476.     long now = 0;
  477.  
  478.     if (millis == 0) {
  479.         while (isAlive()) {
  480.         wait(0);
  481.         }
  482.     } else {
  483.         while (isAlive()) {
  484.         long delay = millis - now;
  485.         if (delay <= 0) {
  486.             break;
  487.         }
  488.         wait(delay);
  489.         now = System.currentTimeMillis() - base;
  490.         }
  491.     }
  492.     }
  493.  
  494.     /**
  495.      * Waits for the Thread to die, with more precise time.
  496.      * @exception InterruptedException 
  497.      *            Another thread has interrupted this thread. 
  498.      */
  499.     public final synchronized void join(long millis, int nanos) throws InterruptedException {
  500.     if (nanos >= 500000 || millis == 0)
  501.         millis++;
  502.     join(millis);
  503.     }
  504.  
  505.  
  506.     /**
  507.      * Waits forever for this Thread to die.
  508.      * @exception InterruptedException 
  509.      *            Another thread has interrupted this thread. 
  510.      */
  511.     public final void join() throws InterruptedException {
  512.     join(0);
  513.     }
  514.  
  515.     /**
  516.      * A debugging procedure to print a stack trace for the
  517.      * current Thread.
  518.      * @see Throwable#printStackTrace
  519.      */
  520.     public static void dumpStack() {
  521.     new Exception("Stack trace").printStackTrace();
  522.     }
  523.  
  524.     /**
  525.      * Marks this Thread as a daemon Thread or a user Thread.
  526.      * When there are only daemon Threads left running in the
  527.      * system, Java exits.
  528.      * @param on    determines whether the Thread will be a daemon Thread
  529.      * @exception IllegalThreadStateException If the Thread is active.
  530.      * @see Thread#isDaemon
  531.      */
  532.     public final void setDaemon(boolean on) {
  533.     checkAccess();
  534.     if (isAlive()) {
  535.         throw new IllegalThreadStateException();
  536.     }
  537.     daemon = on;
  538.     }
  539.  
  540.     /**
  541.      * Returns the daemon flag of the Thread.
  542.      * @see Thread#setDaemon
  543.      */
  544.     public final boolean isDaemon() {
  545.     return daemon;
  546.     }
  547.  
  548.     /**
  549.      * Checks whether the current Thread is allowed to modify this Thread.
  550.      * @exception SecurityException If the current Thread is not allowed 
  551.      * to access this Thread group.
  552.      */
  553.     public void checkAccess() {
  554.     SecurityManager security = System.getSecurityManager();
  555.     if (security != null) {
  556.         security.checkAccess(this);
  557.     }
  558.     }
  559.  
  560.     /**
  561.      * Returns a String representation of the Thread, including the 
  562.      * thread's name, priority and thread group.
  563.      */
  564.     public String toString() {
  565.     return "Thread[" + getName() + "," + getPriority() + "," + 
  566.             getThreadGroup().getName() + "]";
  567.     }
  568.  
  569.     /* Some private helper methods */
  570.     private native void setPriority0(int newPriority);
  571.     private native void stop0(Object o);
  572.     private native void suspend0();
  573.     private native void resume0();
  574. }
  575.