threadgroup.java

来自「《移动Agent技术》一书的所有章节源代码。」· Java 代码 · 共 842 行 · 第 1/2 页

JAVA
842
字号
/*
 * @(#)ThreadGroup.java	1.33 98/01/21
 *
 * Copyright (c) 1995, 1996 Sun Microsystems, Inc. All Rights Reserved.
 *
 * This software is the confidential and proprietary information of Sun
 * Microsystems, Inc. ("Confidential Information").  You shall not
 * disclose such Confidential Information and shall use it only in
 * accordance with the terms of the license agreement you entered into
 * with Sun.
 *
 * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
 * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
 * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
 * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
 * THIS SOFTWARE OR ITS DERIVATIVES.
 *
 * CopyrightVersion 1.1_beta
 *
 */

package java.lang;

import java.io.PrintStream;
import sun.misc.VM;

/**
 * A thread group represents a set of threads. In addition, a thread
 * group can also include other thread groups. The thread groups form
 * a tree in which every thread group except the initial thread group
 * has a parent.
 * <p>
 * A thread is allowed to access information about its own thread
 * group, but not to access information about its thread group's
 * parent thread group or any other thread groups.
 *
 * @author  unascribed
 * @version 1.33, 01/21/98
 * @since   JDK1.0
 */
/* The locking strategy for this code is to try to lock only one level of the
 * tree wherever possible, but otherwise to lock from the bottom up.
 * That is, from child thread groups to parents.
 * This has the advantage of limiting the number of locks that need to be held
 * and in particular avoids having to grab the lock for the root thread group,
 * (or a global lock) which would be a source of contention on a
 * multi-processor system with many thread groups.
 * This policy often leads to taking a snapshot of the state of a thread group
 * and working off of that snapshot, rather than holding the thread group locked
 * while we work on the children.
 */
public
class ThreadGroup {
    ThreadGroup parent;
    String name;
    int maxPriority;
    boolean destroyed;
    boolean daemon;
    boolean vmAllowSuspension;

    int nthreads;
    Thread threads[];

    int ngroups;
    ThreadGroup groups[];

    /**
     * Creates an empty Thread group that is not in any Thread group.
     * This method is used to create the system Thread group.
     */
    private ThreadGroup() {	// called from C code
	this.name = "system";
	this.maxPriority = Thread.MAX_PRIORITY;
    }

    /**
     * Constructs a new thread group. The parent of this new group is
     * the thread group of the currently running thread.
     *
     * @param   name   the name of the new thread group.
     * @since   JDK1.0
     */
    public ThreadGroup(String name) {
	this(Thread.currentThread().getThreadGroup(), name);
    }

    /**
     * Creates a new thread group. The parent of this new group is the
     * specified thread group.
     * <p>
     * The <code>checkAccess</code> method of the parent thread group is
     * called with no arguments; this may result in a security exception.
     *
     * @param     parent   the parent thread group.
     * @param     name     the name of the new thread group.
     * @exception  NullPointerException  if the thread group argument is
     *               <code>null</code>.
     * @exception  SecurityException  if the current thread cannot create a
     *               thread in the specified thread group.
     * @see     java.lang.SecurityException
     * @see     java.lang.ThreadGroup#checkAccess()
     * @since   JDK1.0
     */
    public ThreadGroup(ThreadGroup parent, String name) {
	if (parent == null) {
	    throw new NullPointerException();
	}
	parent.checkAccess();
	this.name = name;
	this.maxPriority = parent.maxPriority;
	this.daemon = parent.daemon;
	this.vmAllowSuspension = parent.vmAllowSuspension;
	this.parent = parent;
	parent.add(this);
    }

    /**
     * Returns the name of this thread group.
     *
     * @return  the name of this thread group.
     * @since   JDK1.0
     */
    public final String getName() {
	return name;
    }

    /**
     * Returns the parent of this thread group.
     *
     * @return  the parent of this thread group. The top-level thread group
     *          is the only thread group whose parent is <code>null</code>.
     * @since   JDK1.0
     */
    public final ThreadGroup getParent() {
        checkAccess();
	return parent;
    }

    /**
     * Returns the maximum priority of this thread group. Threads that are
     * part of this group cannot have a higher priority than the maximum
     * priority.
     *
     * @return  the maximum priority that a thread in this thread group
     *          can have.
     * @since   JDK1.0
     */
    public final int getMaxPriority() {
	return maxPriority;
    }

    /**
     * Tests if this thread group is a daemon thread group. A
     * daemon thread group is automatically destroyed when its last
     * thread is stopped or its last thread group is destroyed.
     *
     * @return  <code>true</code> if this thread group is a daemon thread group;
     *          <code>false</code> otherwise.
     * @since   JDK1.0
     */
    public final boolean isDaemon() {
	return daemon;
    }

    /**
     * Tests if this thread group has been destroyed.
     *
     * @since   JDK1.1
     */
    public synchronized boolean isDestroyed() {
	return destroyed;
    }

    /**
     * Changes the daemon status of this thread group.
     * <p>
     * First, the <code>checkAccess</code> method of this thread group is
     * called with no arguments; this may result in a security exception.
     * <p>
     * A daemon thread group is automatically destroyed when its last
     * thread is stopped or its last thread group is destroyed.
     *
     * @param      daemon   if <code>true</code>, marks this thread group as
     *                      a daemon thread group; otherwise, marks this
     *                      thread group as normal.
     * @exception  SecurityException  if the current thread cannot modify
     *               this thread.
     * @see        java.lang.SecurityException
     * @see        java.lang.ThreadGroup#checkAccess()
     * @since      JDK1.0
     */
    public final void setDaemon(boolean daemon) {
	checkAccess();
	this.daemon = daemon;
    }

    /**
     * Sets the maximum priority of the group.
     * <p>
     * First, the <code>checkAccess</code> method of this thread group is
     * called with no arguments; this may result in a security exception.
     * <p>
     * Threads in the thread group that already have a higher priority
     * are not affected.
     *
     * @param      pri   the new priority of the thread group.
     * @exception  SecurityException  if the current thread cannot modify
     *               this thread group.
     * @see        java.lang.SecurityException
     * @see        java.lang.ThreadGroup#checkAccess()
     * @since      JDK1.0
     */
    public final void setMaxPriority(int pri) {
	int ngroupsSnapshot;
	ThreadGroup[] groupsSnapshot;
	synchronized (this) {
	    checkAccess();
	    if (pri < Thread.MIN_PRIORITY) {
		maxPriority = Thread.MIN_PRIORITY;
	    } else if (pri < maxPriority) {
		maxPriority = pri;
	    }
	    ngroupsSnapshot = ngroups;
	    if (groups != null) {
		groupsSnapshot = new ThreadGroup[ngroupsSnapshot];
		System.arraycopy(groups, 0, groupsSnapshot, 0, ngroupsSnapshot);
	    } else {
		groupsSnapshot = null;
	    }
	}
	for (int i = 0 ; i < ngroupsSnapshot ; i++) {
	    groupsSnapshot[i].setMaxPriority(pri);
	}
    }

    /**
     * Tests if this thread group is either the thread group
     * argument or one of its ancestor thread groups.
     *
     * @param   g   a thread group.
     * @return  <code>true</code> if this thread group is the thread group
     *          argument or one of its ancestor thread groups;
     *          <code>false</code> otherwise.
     * @since   JDK1.0
     */
    public final boolean parentOf(ThreadGroup g) {
	for (; g != null ; g = g.parent) {
	    if (g == this) {
		return true;
	    }
	}
	return false;
    }

    /**
     * Determines if the currently running thread has permission to
     * modify this thread group.
     * <p>
     * If there is a security manager, its <code>checkAccess</code> method
     * is called with this thread group as its argument. This may result
     * in throwing a <code>SecurityException</code>.
     *
     * @exception  SecurityException  if the current thread is not allowed to
     *               access this thread group.
     * @see        java.lang.SecurityManager#checkAccess(java.lang.ThreadGroup)
     * @since      JDK1.0
     */
    public final void checkAccess() {
	SecurityManager security = System.getSecurityManager();
	if (security != null) {
	    security.checkAccess(this);
	}
    }

    /**
     * Returns an estimate of the number of active threads in this
     * thread group.
     *
     * @return  the number of active threads in this thread group and in any
     *          other thread group that has this thread group as an ancestor.
     * @since   JDK1.0
     */
    public int activeCount() {
	int result;
	// Snapshot sub-group data so we don't hold this lock
	// while our children are computing.
	int ngroupsSnapshot;
	ThreadGroup[] groupsSnapshot;
	synchronized (this) {
	    if (destroyed) {
		return 0;
	    }
	    result = nthreads;
	    ngroupsSnapshot = ngroups;
	    if (groups != null) {
		groupsSnapshot = new ThreadGroup[ngroupsSnapshot];
		System.arraycopy(groups, 0, groupsSnapshot, 0, ngroupsSnapshot);
	    } else {
		groupsSnapshot = null;
	    }
	}
	for (int i = 0 ; i < ngroupsSnapshot ; i++) {
	    result += groupsSnapshot[i].activeCount();
	}
	return result;
    }

    /**
     * Copies into the specified array every active thread in this
     * thread group and its subgroups.
     * <p>
     * An application should use the <code>activeCount</code> method to
     * get an estimate of how big the array should be. If the array is
     * too short to hold all the threads, the extra threads are silently
     * ignored.
     *
     * @param   list   an array into which to place the list of threads.
     * @return  the number of threads put into the array.
     * @see     java.lang.ThreadGroup#activeCount()
     * @since   JDK1.0
     */
    public int enumerate(Thread list[]) {
	return enumerate(list, 0, true);
    }

    /**
     * Copies into the specified array every active thread in this
     * thread group. If the <code>recurse</code> flag is
     * <code>true</code>, references to every active thread in this
     * thread's subgroups are also included. If the array is too short to
     * hold all the threads, the extra threads are silently ignored.
     * <p>
     * An application should use the <code>activeCount</code> method to
     * get an estimate of how big the array should be.
     *
     * @param   list      an array into which to place the list of threads.
     * @param   recurse   a flag indicating whether also to include threads
     *                    in thread groups that are subgroups of this
     *                    thread group.
     * @return  the number of threads placed into the array.
     * @see     java.lang.ThreadGroup#activeCount()
     * @since   JDK1.0
     */
    public int enumerate(Thread list[], boolean recurse) {
	return enumerate(list, 0, recurse);
    }

    private int enumerate(Thread list[], int n, boolean recurse) {
	int ngroupsSnapshot = 0;
	ThreadGroup[] groupsSnapshot = null;
	synchronized (this) {
	    if (destroyed) {
		return 0;
	    }
	    int nt = nthreads;
	    if (nt > list.length - n) {
		nt = list.length - n;
	    }
	    if (nt > 0) {
		System.arraycopy(threads, 0, list, n, nt);
		n += nt;
	    }
	    if (recurse) {
		ngroupsSnapshot = ngroups;
		if (groups != null) {
		    groupsSnapshot = new ThreadGroup[ngroupsSnapshot];
		    System.arraycopy(groups, 0, groupsSnapshot, 0, ngroupsSnapshot);
		} else {
		    groupsSnapshot = null;
		}
	    }
	}
	if (recurse) {
	    for (int i = 0 ; i < ngroupsSnapshot ; i++) {
		n = groupsSnapshot[i].enumerate(list, n, true);
	    }
	}
	return n;
    }

    /**
     * Returns an estimate of the number of active groups in this
     * thread group.
     *
     * @return  the number of active thread groups with this thread group as
     *          an ancestor.
     * @since   JDK1.0
     */
    public int activeGroupCount() {
	int ngroupsSnapshot;
	ThreadGroup[] groupsSnapshot;
	synchronized (this) {
	    if (destroyed) {
		return 0;
	    }
	    ngroupsSnapshot = ngroups;
	    if (groups != null) {
		groupsSnapshot = new ThreadGroup[ngroupsSnapshot];
		System.arraycopy(groups, 0, groupsSnapshot, 0, ngroupsSnapshot);
	    } else {
		groupsSnapshot = null;
	    }
	}
	int n = ngroupsSnapshot;
	for (int i = 0 ; i < ngroupsSnapshot ; i++) {
	    n += groupsSnapshot[i].activeGroupCount();
	}
	return n;
    }

    /**
     * Copies into the specified array references to every active
     * subgroup in this thread group.
     * <p>
     * An application should use the <code>activeGroupCount</code>
     * method to get an estimate of how big the array should be. If the
     * array is too short to hold all the thread groups, the extra thread
     * groups are silently ignored.
     *
     * @param   list   an array into which to place the list of thread groups.

⌨️ 快捷键说明

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