home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1997 May / Pcwk0597.iso / sybase / starbuck / java.z / Thread.java < prev    next >
Text File  |  1996-05-03  |  18KB  |  588 lines

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