/** * 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); saveThreadStarterClassFlag = parent.saveThreadStarterClassFlag; }
/** * Sets the priority of this thread. If the requested priority is greater than the parent thread * group's {@link java.lang.ThreadGroup#getMaxPriority}, the group's maximum priority will be used * instead. * * @throws IllegalArgumentException - if the new priority is greater than {@link #MAX_PRIORITY} or * less than {@link #MIN_PRIORITY} */ public final void setPriority(int priority) { if (priority < Thread.MIN_PRIORITY || priority > Thread.MAX_PRIORITY) { throw new IllegalArgumentException("Priority out of range: " + priority); } if (priority > group.getMaxPriority()) { priority = group.getMaxPriority(); } this.priority = priority; VMThread vmt = this.vmThread; if (vmt != null) { vmt.setPriority(priority); } }
/** * Destroys this thread group and all of its subgroups. This thread group must be empty, * indicating that all threads that had been in this thread group have since stopped. * * <p>First, the <code>checkAccess</code> method of this thread group is called with no arguments; * this may result in a security exception. * * @exception IllegalThreadStateException if the thread group is not empty or if the thread group * has already been destroyed. * @exception SecurityException if the current thread cannot modify this thread group. * @see java.lang.ThreadGroup#checkAccess() * @since JDK1.0 */ public final void destroy() { int ngroupsSnapshot; ThreadGroup[] groupsSnapshot; synchronized (this) { checkAccess(); if (destroyed || (nthreads > 0)) { throw new IllegalThreadStateException(); } ngroupsSnapshot = ngroups; if (groups != null) { groupsSnapshot = new ThreadGroup[ngroupsSnapshot]; System.arraycopy(groups, 0, groupsSnapshot, 0, ngroupsSnapshot); } else { groupsSnapshot = null; } if (parent != null) { destroyed = true; ngroups = 0; groups = null; nthreads = 0; threads = null; } } for (int i = 0; i < ngroupsSnapshot; i += 1) { groupsSnapshot[i].destroy(); } if (parent != null) { parent.remove(this); } }
/** * Called by the Java Virtual Machine when a thread in this thread group stops because of an * uncaught exception. * * <p>The <code>uncaughtException</code> method of <code>ThreadGroup</code> does the following: * * <ul> * <li>If this thread group has a parent thread group, the <code>uncaughtException</code> method * of that parent is called with the same two arguments. * <li>Otherwise, this method determines if the <code>Throwable</code> argument is an instance * of <code>ThreadDeath</code>. If so, nothing special is done. Otherwise, the <code> * Throwable</code>'s <code>printStackTrace</code> method is called to print a stack * backtrace to the standard error stream. * </ul> * * <p>Applications can override this method in subclasses of <code>ThreadGroup</code> to provide * alternative handling of uncaught exceptions. * * @param t the thread that is about to exit. * @param e the uncaught exception. * @see java.lang.System#err * @see java.lang.ThreadDeath * @see java.lang.Throwable#printStackTrace(java.io.PrintStream) * @since JDK1.0 */ public void uncaughtException(Thread t, Throwable e) { if (parent != null) { parent.uncaughtException(t, e); } else if (!(e instanceof ThreadDeath)) { if (System.err != null) { /* can be null at startup */ e.printStackTrace(System.err); } } }
/** * Initializes a new, existing Thread object with a runnable object, the given name and belonging * to the ThreadGroup passed as parameter. This is the method that the several public constructors * delegate their work to. * * @param group ThreadGroup to which the new Thread will belong * @param runnable a java.lang.Runnable whose method <code>run</code> will be executed by the new * Thread * @param threadName Name for the Thread being created * @param stackSize Platform dependent stack size * @throws IllegalThreadStateException if <code>group.destroy()</code> has already been done * @see java.lang.ThreadGroup * @see java.lang.Runnable */ private void create(ThreadGroup group, Runnable runnable, String threadName, long stackSize) { Thread currentThread = Thread.currentThread(); if (group == null) { group = currentThread.getThreadGroup(); } if (group.isDestroyed()) { throw new IllegalThreadStateException("Group already destroyed"); } this.group = group; synchronized (Thread.class) { id = ++Thread.count; } if (threadName == null) { this.name = "Thread-" + id; } else { this.name = threadName; } this.target = runnable; this.stackSize = stackSize; this.priority = currentThread.getPriority(); this.contextClassLoader = currentThread.contextClassLoader; // Transfer over InheritableThreadLocals. if (currentThread.inheritableValues != null) { inheritableValues = new ThreadLocal.Values(currentThread.inheritableValues); } // add ourselves to our ThreadGroup of choice this.group.addThread(this); }
public static void main(String[] args) { ThreadGroup group = new ThreadGroup("demo"); for (int i = 0; i < 3; i++) { new Thread( group, new Runnable() { public void run() { System.out.print(""); } }) .start(); } group.list(); int count = group.activeCount(); // 获得线程组中活动的线程 System.out.println(count); Thread threads[] = new Thread[group.activeCount()]; group.enumerate(threads); // 将当前线程组中活动的线程复制到一个线程数组中去。 for (Thread thread : threads) { System.out.println(thread.getName()); } ThreadGroup parent = group.getParent(); parent.list(); ThreadGroup parent2 = parent.getParent(); parent2.list(); }
/** * Returns a string containing a concise, human-readable description of the Thread. It includes * the Thread's name, priority, and group name. * * @return a printable representation for the receiver. */ @Override public String toString() { return "Thread[" + name + "," + priority + "," + group.getName() + "]"; }
/** * Returns the parent of this thread group. * * <p>First, if the parent is not <code>null</code>, the <code>checkAccess</code> method of the * parent thread group is called with no arguments; this may result in a security exception. * * @return the parent of this thread group. The top-level thread group is the only thread group * whose parent is <code>null</code>. * @exception SecurityException if the current thread cannot modify this thread group. * @see java.lang.ThreadGroup#checkAccess() * @see java.lang.SecurityException * @see java.lang.RuntimePermission * @since JDK1.0 */ public final ThreadGroup getParent() { if (parent != null) parent.checkAccess(); return parent; }