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 + -
显示快捷键?