Methods Summary |
---|
public int | activeCount()Returns the number of Threads which are children of the receiver,
directly or indirectly and are running.
// BEGIN android-changed
int count = 0;
// Lock the children thread list
synchronized (this.childrenThreadsLock) {
for (int i = 0; i < numThreads; i++) {
if(childrenThreads[i].isAlive()) {
count++;
}
}
}
// END android-changed
// Lock this subpart of the tree as we walk
synchronized (this.childrenGroupsLock) {
for (int i = 0; i < numGroups; i++) {
count += this.childrenGroups[i].activeCount();
}
}
return count;
|
public int | activeGroupCount()Returns the number of ThreadGroups which are children of the receiver,
directly or indirectly.
int count = 0;
// Lock this subpart of the tree as we walk
synchronized (this.childrenGroupsLock) {
for (int i = 0; i < numGroups; i++) {
// One for this group & the subgroups
count += 1 + this.childrenGroups[i].activeGroupCount();
}
}
return count;
|
final void | add(java.lang.Thread thread)Adds a Thread to the receiver. This should only be visible to class
java.lang.Thread, and should only be called when a new Thread is created
and initialized by the constructor.
synchronized (this.childrenThreadsLock) {
if (!isDestroyed) {
if (childrenThreads.length == numThreads) {
Thread[] newThreads = new Thread[childrenThreads.length * 2];
System.arraycopy(childrenThreads, 0, newThreads, 0, numThreads);
newThreads[numThreads++] = thread;
childrenThreads = newThreads;
} else {
childrenThreads[numThreads++] = thread;
}
} else {
throw new IllegalThreadStateException();
}
}
|
private void | add(java.lang.ThreadGroup g)Adds a ThreadGroup to the receiver.
synchronized (this.childrenGroupsLock) {
if (!isDestroyed) {
if (childrenGroups.length == numGroups) {
ThreadGroup[] newGroups = new ThreadGroup[childrenGroups.length * 2];
System.arraycopy(childrenGroups, 0, newGroups, 0, numGroups);
newGroups[numGroups++] = g;
childrenGroups = newGroups;
} else {
childrenGroups[numGroups++] = g;
}
} else {
throw new IllegalThreadStateException();
}
}
|
void | addThread(java.lang.Thread thread)Non-standard method for adding a thread to a group, required by Dalvik.
add(thread);
|
public boolean | allowThreadSuspension(boolean b)Does nothing. The definition of this method depends on the deprecated
method {@link #suspend()}. The exact behavior of this call was never
specified.
// Does not apply to this VM, no-op
return true;
|
public final void | checkAccess()Checks the accessibility of the ThreadGroup from the perspective of the
caller. If there is a SecurityManager installed, calls
{@code checkAccess} with the receiver as a parameter, otherwise does
nothing.
// Forwards the message to the SecurityManager (if there's one) passing
// the receiver as parameter
SecurityManager currentManager = System.getSecurityManager();
if (currentManager != null) {
currentManager.checkAccess(this);
}
|
public final void | destroy()Destroys the receiver and recursively all its subgroups. It is only legal
to destroy a ThreadGroup that has no Threads in it. Any daemon
ThreadGroup is destroyed automatically when it becomes empty (no Threads
and no ThreadGroups in it).
checkAccess();
// Lock this subpart of the tree as we walk
synchronized (this.childrenThreadsLock) {
synchronized (this.childrenGroupsLock) {
// BEGIN android-added
if (this.isDestroyed) {
throw new IllegalThreadStateException(
"Thread group was already destroyed: "
+ (this.name != null ? this.name : "n/a"));
}
if (this.numThreads > 0) {
throw new IllegalThreadStateException(
"Thread group still contains threads: "
+ (this.name != null ? this.name : "n/a"));
}
// END android-added
int toDestroy = numGroups;
// Call recursively for subgroups
for (int i = 0; i < toDestroy; i++) {
// We always get the first element - remember, when the
// child dies it removes itself from our collection. See
// below.
this.childrenGroups[0].destroy();
}
if (parent != null) {
parent.remove(this);
}
// Now that the ThreadGroup is really destroyed it can be tagged
// as so
this.isDestroyed = true;
}
}
|
private void | destroyIfEmptyDaemon()
// Has to be non-destroyed daemon to make sense
synchronized (this.childrenThreadsLock) {
if (isDaemon && !isDestroyed && numThreads == 0) {
synchronized (this.childrenGroupsLock) {
if (numGroups == 0) {
destroy();
}
}
}
}
|
public int | enumerate(java.lang.Thread[] threads)Iterates over all active threads in this group (and its sub-groups) and
stores the threads in the given array. Returns when the array is full or
no more threads remain, whichever happens first.
return enumerate(threads, true);
|
public int | enumerate(java.lang.Thread[] threads, boolean recurse)Iterates over all active threads in this group (and, optionally, its
sub-groups) and stores the threads in the given array. Returns when the
array is full or no more threads remain, whichever happens first.
return enumerateGeneric(threads, recurse, 0, true);
|
public int | enumerate(java.lang.ThreadGroup[] groups)Iterates over all thread groups in this group (and its sub-groups) and
and stores the groups in the given array. Returns when the array is full
or no more groups remain, whichever happens first.
return enumerate(groups, true);
|
public int | enumerate(java.lang.ThreadGroup[] groups, boolean recurse)Iterates over all thread groups in this group (and, optionally, its
sub-groups) and and stores the groups in the given array. Returns when
the array is full or no more groups remain, whichever happens first.
return enumerateGeneric(groups, recurse, 0, false);
|
private int | enumerateGeneric(java.lang.Object[] enumeration, boolean recurse, int enumerationIndex, boolean enumeratingThreads)Copies into enumeration starting at
enumerationIndex all Threads or ThreadGroups in the
receiver. If recurse is true, recursively enumerate the
elements in subgroups.
If the array passed as parameter is too small no exception is thrown -
the extra elements are simply not copied.
checkAccess();
Object[] immediateCollection = enumeratingThreads ? (Object[]) childrenThreads
: (Object[]) childrenGroups;
Object syncLock = enumeratingThreads ? childrenThreadsLock : childrenGroupsLock;
synchronized (syncLock) { // Lock this subpart of the tree as we walk
for (int i = enumeratingThreads ? numThreads : numGroups; --i >= 0;) {
if (!enumeratingThreads || ((Thread) immediateCollection[i]).isAlive()) {
if (enumerationIndex >= enumeration.length) {
return enumerationIndex;
}
enumeration[enumerationIndex++] = immediateCollection[i];
}
}
}
if (recurse) { // Lock this subpart of the tree as we walk
synchronized (this.childrenGroupsLock) {
for (int i = 0; i < numGroups; i++) {
if (enumerationIndex >= enumeration.length) {
return enumerationIndex;
}
enumerationIndex = childrenGroups[i].enumerateGeneric(enumeration, recurse,
enumerationIndex, enumeratingThreads);
}
}
}
return enumerationIndex;
|
public final int | getMaxPriority()Returns the maximum allowed priority for a Thread in the receiver.
return maxPriority;
|
public final java.lang.String | getName()Returns the name of the receiver.
return name;
|
public final java.lang.ThreadGroup | getParent()Returns the receiver's parent ThreadGroup. It can be {@code null} if the
receiver is the the root ThreadGroup.
if (parent != null) {
parent.checkAccess();
}
return parent;
|
public final void | interrupt()Interrupts every Thread in the receiver and recursively in all its
subgroups.
checkAccess();
// Lock this subpart of the tree as we walk
synchronized (this.childrenThreadsLock) {
for (int i = 0; i < numThreads; i++) {
this.childrenThreads[i].interrupt();
}
}
// Lock this subpart of the tree as we walk
synchronized (this.childrenGroupsLock) {
for (int i = 0; i < numGroups; i++) {
this.childrenGroups[i].interrupt();
}
}
|
public final boolean | isDaemon()Checks whether the receiver is a daemon ThreadGroup.
return isDaemon;
|
public synchronized boolean | isDestroyed()Checks whether the receiver has already been destroyed.
return isDestroyed;
|
public void | list()Outputs to {@code System.out} a text representation of the
hierarchy of Threads and ThreadGroups in the receiver (and recursively).
Proper indentation is done to suggest the nesting of groups inside groups
and threads inside groups.
// We start in a fresh line
System.out.println();
list(0);
|
private void | list(int levels)
for (int i = 0; i < levels; i++) {
System.out.print(" "); // 4 spaces for each level
}
// Print the receiver
System.out.println(this.toString());
// Print the children threads, with 1 extra indentation
synchronized (this.childrenThreadsLock) {
for (int i = 0; i < numThreads; i++) {
// children get an extra indentation, 4 spaces for each level
for (int j = 0; j <= levels; j++) {
System.out.print(" ");
}
System.out.println(this.childrenThreads[i]);
}
}
synchronized (this.childrenGroupsLock) {
for (int i = 0; i < numGroups; i++) {
this.childrenGroups[i].list(levels + 1);
}
}
|
public final boolean | parentOf(java.lang.ThreadGroup g)Checks whether the receiver is a direct or indirect parent group of a
given ThreadGroup.
while (g != null) {
if (this == g) {
return true;
}
g = g.parent;
}
return false;
|
final void | remove(java.lang.Thread thread)Removes a Thread from the receiver. This should only be visible to class
java.lang.Thread, and should only be called when a Thread dies.
synchronized (this.childrenThreadsLock) {
for (int i = 0; i < numThreads; i++) {
if (childrenThreads[i].equals(thread)) {
numThreads--;
System
.arraycopy(childrenThreads, i + 1, childrenThreads, i, numThreads
- i);
childrenThreads[numThreads] = null;
break;
}
}
}
destroyIfEmptyDaemon();
|
private void | remove(java.lang.ThreadGroup g)Removes an immediate subgroup from the receiver.
synchronized (this.childrenGroupsLock) {
for (int i = 0; i < numGroups; i++) {
if (childrenGroups[i].equals(g)) {
numGroups--;
System.arraycopy(childrenGroups, i + 1, childrenGroups, i, numGroups - i);
childrenGroups[numGroups] = null;
break;
}
}
}
destroyIfEmptyDaemon();
|
void | removeThread(java.lang.Thread thread)Non-standard method for adding a thread to a group, required by Dalvik.
remove(thread);
|
public final void | resume()Resumes every Thread in the receiver and recursively in all its
subgroups.
checkAccess();
// Lock this subpart of the tree as we walk
synchronized (this.childrenThreadsLock) {
for (int i = 0; i < numThreads; i++) {
this.childrenThreads[i].resume();
}
}
// Lock this subpart of the tree as we walk
synchronized (this.childrenGroupsLock) {
for (int i = 0; i < numGroups; i++) {
this.childrenGroups[i].resume();
}
}
|
public final void | setDaemon(boolean isDaemon)Configures the receiver to be a daemon ThreadGroup or not. Daemon
ThreadGroups are automatically destroyed when they become empty.
checkAccess();
this.isDaemon = isDaemon;
|
public final void | setMaxPriority(int newMax)Configures the maximum allowed priority for a Thread in the receiver and
recursively in all its subgroups.
One can never change the maximum priority of a ThreadGroup to be higher
than it was. Such an attempt will not result in an exception, it will
simply leave the ThreadGroup with its current maximum priority.
checkAccess();
if (newMax <= this.maxPriority) {
if (newMax < Thread.MIN_PRIORITY) {
newMax = Thread.MIN_PRIORITY;
}
int parentPriority = parent == null ? newMax : parent.getMaxPriority();
this.maxPriority = parentPriority <= newMax ? parentPriority : newMax;
// Lock this subpart of the tree as we walk
synchronized (this.childrenGroupsLock) {
// ??? why not maxPriority
for (int i = 0; i < numGroups; i++) {
this.childrenGroups[i].setMaxPriority(newMax);
}
}
}
|
private void | setParent(java.lang.ThreadGroup parent)Sets the parent ThreadGroup of the receiver, and adds the receiver to the
parent's collection of immediate children (if {@code parent} is
not {@code null}).
if (parent != null) {
parent.add(this);
}
this.parent = parent;
|
public final void | stop()Stops every Thread in the receiver and recursively in all its subgroups.
if (stopHelper()) {
Thread.currentThread().stop();
}
|
private final boolean | stopHelper()
checkAccess();
boolean stopCurrent = false;
// Lock this subpart of the tree as we walk
synchronized (this.childrenThreadsLock) {
Thread current = Thread.currentThread();
for (int i = 0; i < numThreads; i++) {
if (this.childrenThreads[i] == current) {
stopCurrent = true;
} else {
this.childrenThreads[i].stop();
}
}
}
// Lock this subpart of the tree as we walk
synchronized (this.childrenGroupsLock) {
for (int i = 0; i < numGroups; i++) {
stopCurrent |= this.childrenGroups[i].stopHelper();
}
}
return stopCurrent;
|
public final void | suspend()Suspends every Thread in the receiver and recursively in all its
subgroups.
if (suspendHelper()) {
Thread.currentThread().suspend();
}
|
private final boolean | suspendHelper()
checkAccess();
boolean suspendCurrent = false;
// Lock this subpart of the tree as we walk
synchronized (this.childrenThreadsLock) {
Thread current = Thread.currentThread();
for (int i = 0; i < numThreads; i++) {
if (this.childrenThreads[i] == current) {
suspendCurrent = true;
} else {
this.childrenThreads[i].suspend();
}
}
}
// Lock this subpart of the tree as we walk
synchronized (this.childrenGroupsLock) {
for (int i = 0; i < numGroups; i++) {
suspendCurrent |= this.childrenGroups[i].suspendHelper();
}
}
return suspendCurrent;
|
public java.lang.String | toString()Returns a string containing a concise, human-readable description of the
receiver.
return getClass().getName() + "[name=" + this.getName() + ",maxpri="
+ this.getMaxPriority() + "]";
|
public void | uncaughtException(java.lang.Thread t, java.lang.Throwable e)Handles uncaught exceptions. Any uncaught exception in any Thread
is forwarded (by the VM) to the Thread's ThreadGroup by sending this
message (uncaughtException). This allows users to define custom
ThreadGroup classes and custom behavior for when a Thread has an
uncaughtException or when it does (ThreadDeath).
// BEGIN android-changed
if (parent != null) {
parent.uncaughtException(t, e);
} else if (Thread.getDefaultUncaughtExceptionHandler() != null) {
// TODO The spec is unclear regarding this. What do we do?
Thread.getDefaultUncaughtExceptionHandler().uncaughtException(t, e);
} else if (!(e instanceof ThreadDeath)) {
// No parent group, has to be 'system' Thread Group
e.printStackTrace(System.err);
}
// END android-changed
|