home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 1997 October
/
Chip_1997-10_cd.bin
/
tema
/
sybase
/
powerj
/
java.z
/
ThreadGroup.java
< prev
next >
Wrap
Text File
|
1996-05-03
|
13KB
|
487 lines
/*
* @(#)ThreadGroup.java 1.23 96/03/25
*
* Copyright (c) 1994 Sun Microsystems, Inc. All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software
* and its documentation for NON-COMMERCIAL purposes and without
* fee is hereby granted provided that this copyright notice
* appears in all copies. Please refer to the file "copyright.html"
* for further important copyright and licensing information.
*
* 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.
*/
package java.lang;
import java.io.PrintStream;
/**
* A group of Threads. A Thread group can contain a set of Threads
* as well as a set of other Thread groups. A Thread can access its
* Thread group, but it can't access the parent of its Thread group.
* This makes it possible to encapsulate a Thread in a Thread group
* and stop it from manipulating Threads in the parent group.
*
* @version 1.23, 25 Mar 1996
* @author Arthur van Hoff
*/
public
class ThreadGroup {
ThreadGroup parent;
String name;
int maxPriority;
boolean destroyed;
boolean daemon;
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;
}
/**
* Creates a new ThreadGroup. Its parent will be the Thread group
* of the current Thread.
* @param name the name of the new Thread group created
*/
public ThreadGroup(String name) {
this(Thread.currentThread().getThreadGroup(), name);
}
/**
* Creates a new ThreadGroup with a specified name in the specified Thread group.
* @param parent the specified parent Thread group
* @param name the name of the new Thread group being created
* @exception NullPointerException If the given thread group is equal to null.
*/
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.parent = parent;
parent.add(this);
}
/**
* Gets the name of this Thread group.
*/
public final String getName() {
return name;
}
/**
* Gets the parent of this Thread group.
*/
public final ThreadGroup getParent() {
return parent;
}
/**
* Gets the maximum priority of the group. Threads that are
* part of this group cannot have a higher priority than the maximum priority.
*/
public final int getMaxPriority() {
return maxPriority;
}
/**
* Returns the daemon flag of the Thread group. A daemon Thread group
* is automatically destroyed when it is found empty after a Thread
* group or Thread is removed from it.
*/
public final boolean isDaemon() {
return daemon;
}
/**
* Changes the daemon status of this group.
* @param daemon the daemon boolean which is to be set.
*/
public final void setDaemon(boolean daemon) {
checkAccess();
this.daemon = daemon;
}
/**
* Sets the maximum priority of the group. Threads
* that are already in the group <b>can</b> have a higher priority than the
* set maximum.
* @param pri the priority of the Thread group
*/
public final synchronized void setMaxPriority(int pri) {
checkAccess();
if (pri < Thread.MIN_PRIORITY) {
maxPriority = Thread.MIN_PRIORITY;
} else if (pri < maxPriority) {
maxPriority = pri;
}
for (int i = 0 ; i < ngroups ; i++) {
groups[i].setMaxPriority(pri);
}
}
/**
* Checks to see if this Thread group is a parent of or is equal to
* another Thread group.
* @param g the Thread group to be checked
* @return true if this Thread group is equal to or is the parent of another Thread
* group; false otherwise.
*/
public final boolean parentOf(ThreadGroup g) {
for (; g != null ; g = g.parent) {
if (g == this) {
return true;
}
}
return false;
}
/**
* Checks to see if the current Thread is allowed to modify this group.
* @exception SecurityException If the current Thread is not allowed
* to access this Thread group.
*/
public final void checkAccess() {
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkAccess(this);
}
}
/**
* Returns an estimate of the number of active Threads in the
* Thread group.
*/
public synchronized int activeCount() {
if (destroyed) {
return 0;
}
int n = nthreads;
for (int i = 0 ; i < ngroups ; i++) {
n += groups[i].activeCount();
}
return n;
}
/**
* Copies, into the specified array, references to every active Thread in this Thread group.
* You can use the activeCount() method to get an estimate of how big
* the array should be.
* @param list an array of Threads
* @return the number of Threads put into the array
*/
public int enumerate(Thread list[]) {
return enumerate(list, 0, true);
}
/**
* Copies, into the specified array, references to every active Thread in this Thread group.
* You can use the activeCount() method to get an estimate of how big
* the array should be.
* @param list an array list of Threads
* @param recurse a boolean indicating whether a Thread has reapearred
* @return the number of Threads placed into the array.
*/
public int enumerate(Thread list[], boolean recurse) {
return enumerate(list, 0, recurse);
}
private synchronized int enumerate(Thread list[], int n, boolean recurse) {
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) {
for (int i = 0 ; i < ngroups ; i++) {
n = groups[i].enumerate(list, n, true);
}
}
return n;
}
/**
* Returns an estimate of the number of active groups in the
* Thread group.
*/
public synchronized int activeGroupCount() {
if (destroyed) {
return 0;
}
int n = ngroups;
for (int i = 0 ; i < ngroups ; i++) {
n += groups[i].activeGroupCount();
}
return n;
}
/**
* Copies, into the specified array, references to every active Thread group in this Thread
* group. You can use the activeGroupCount() method to get an estimate of how big
* the array should be.
* @param list an array of Thread groups
* @return the number of Thread groups placed into the array.
*/
public int enumerate(ThreadGroup list[]) {
return enumerate(list, 0, true);
}
/**
* Copies, into the specified array, references to every active Thread group in this Thread
* group. You can use the activeGroupCount() method to get an estimate of how big
* the array should be.
* @param list an array list of Thread groups
* @param recurse a boolean indicating if a Thread group has reappeared
* @return the number of Thread groups placed into the array.
*/
public int enumerate(ThreadGroup list[], boolean recurse) {
return enumerate(list, 0, recurse);
}
private synchronized int enumerate(ThreadGroup list[], int n, boolean recurse) {
if (destroyed) {
return 0;
}
int ng = ngroups;
if (ng > list.length - n) {
ng = list.length - n;
}
if (ng > 0) {
System.arraycopy(groups, 0, list, n, ng);
n += ng;
}
if (recurse) {
for (int i = 0 ; i < ngroups ; i++) {
n = groups[i].enumerate(list, n, true);
}
}
return n;
}
/**
* Stops all the Threads in this Thread group and all of its sub groups.
*/
public final synchronized void stop() {
checkAccess();
for (int i = 0 ; i < ngroups ; i++) {
groups[i].stop();
}
for (int i = 0 ; i < nthreads ; i++) {
threads[i].stop();
}
}
/**
* Suspends all the Threads in this Thread group and all of its sub groups.
*/
public final synchronized void suspend() {
checkAccess();
for (int i = 0 ; i < ngroups ; i++) {
groups[i].suspend();
}
for (int i = 0 ; i < nthreads ; i++) {
threads[i].suspend();
}
}
/**
* Resumes all the Threads in this Thread group and all of its sub groups.
*/
public final synchronized void resume() {
checkAccess();
for (int i = 0 ; i < ngroups ; i++) {
groups[i].resume();
}
for (int i = 0 ; i < nthreads ; i++) {
threads[i].resume();
}
}
/**
* Destroys a Thread group. This does <b>NOT</b> stop the Threads
* in the Thread group.
* @exception IllegalThreadStateException If the Thread group is not empty
* or if the Thread group was already destroyed.
*/
public final synchronized void destroy() {
checkAccess();
if (destroyed || (nthreads > 0)) {
throw new IllegalThreadStateException();
}
while (ngroups > 0) {
groups[0].destroy();
}
if (parent != null) {
destroyed = true;
groups = null;
threads = null;
parent.remove(this);
}
}
/**
* Adds the specified Thread group to this group.
* @param g the specified Thread group to be added
* @exception IllegalThreadStateException If the Thread group has been destroyed.
*/
private final synchronized void add(ThreadGroup g){
if (destroyed) {
throw new IllegalThreadStateException();
}
if (groups == null) {
groups = new ThreadGroup[4];
} else if (ngroups == groups.length) {
ThreadGroup newgroups[] = new ThreadGroup[ngroups * 2];
System.arraycopy(groups, 0, newgroups, 0, ngroups);
groups = newgroups;
}
groups[ngroups] = g;
// This is done last so it doesn't matter in case the
// thread is killed
ngroups++;
}
/**
* Removes the specified Thread group from this group.
* @param g the Thread group to be removed
* @return if this Thread has already been destroyed.
*/
private synchronized void remove(ThreadGroup g) {
if (destroyed) {
return;
}
for (int i = 0 ; i < ngroups ; i++) {
if (groups[i] == g) {
System.arraycopy(groups, i + 1, groups, i, --ngroups - i);
// Zap dangling reference to the dead group so that
// the garbage collector will collect it.
groups[ngroups] = null;
break;
}
}
if (nthreads == 0) {
notifyAll();
}
if (daemon && (nthreads == 0) && (ngroups == 0)) {
destroy();
}
}
/**
* Adds the specified Thread to this group.
* @param t the Thread to be added
* @exception IllegalThreadStateException If the Thread group has been destroyed.
*/
synchronized void add(Thread t) {
if (destroyed) {
throw new IllegalThreadStateException();
}
if (threads == null) {
threads = new Thread[4];
} else if (nthreads == threads.length) {
Thread newthreads[] = new Thread[nthreads * 2];
System.arraycopy(threads, 0, newthreads, 0, nthreads);
threads = newthreads;
}
threads[nthreads] = t;
// This is done last so it doesn't matter in case the
// thread is killed
nthreads++;
}
/**
* Removes the specified Thread from this group.
* @param t the Thread to be removed
* @return if the Thread has already been destroyed.
*/
synchronized void remove(Thread t) {
if (destroyed) {
return;
}
for (int i = 0 ; i < nthreads ; i++) {
if (threads[i] == t) {
System.arraycopy(threads, i + 1, threads, i, --nthreads - i);
// Zap dangling reference to the dead thread so that
// the garbage collector will collect it.
threads[nthreads] = null;
break;
}
}
if (nthreads == 0) {
notifyAll();
}
if (daemon && (nthreads == 0) && (ngroups == 0)) {
destroy();
}
}
/**
* Lists this Thread group. Useful for debugging only.
*/
public synchronized void list() {
list(System.out, 0);
}
void list(PrintStream out, int indent) {
for (int j = 0 ; j < indent ; j++) {
out.print(" ");
}
out.println(this);
indent += 4;
for (int i = 0 ; i < nthreads ; i++) {
for (int j = 0 ; j < indent ; j++) {
out.print(" ");
}
out.println(threads[i]);
}
for (int i = 0 ; i < ngroups ; i++) {
groups[i].list(out, indent);
}
}
/**
* Called when a thread in this group exists because of
* an uncaught exception.
*/
public void uncaughtException(Thread t, Throwable e) {
if (parent != null) {
parent.uncaughtException(t, e);
} else if (!(e instanceof ThreadDeath)) {
e.printStackTrace(System.err);
}
}
/**
* Returns a String representation of the Thread group.
*/
public String toString() {
return getClass().getName() + "[name=" + getName() + ",maxpri=" + maxPriority + "]";
}
}