1. Class definition

public class ThreadGroup implements Thread.UncaughtExceptionHandler
Copy the code

You can see this in the class definition

  • ThreadGroup implements Thread. UncaughtExceptionHandler interface

The JDK is introduced

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.

A thread group represents a group of threads. In addition, thread groups can include other thread groups. Thread groups form a tree in which each thread group except the initial thread group has a parent

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.

Threads are allowed to access information about their own thread group, but not about their thread group’s parent thread group or any other thread group

2. Field attributes

// Parent thread group
private final ThreadGroup parent;
// The thread group name
String name;
// Maximum priority of a thread group
int maxPriority;
// Destroy state
boolean destroyed;
True: daemon thread group false: common thread group
boolean daemon;
boolean vmAllowSuspension;
// The number of threads not started, i.e. the number of threads in the NEW state
int nUnstartedThreads = 0;
// Size of the thread array
int nthreads;
// The thread of the current thread group
Thread threads[];
// The size of the child thread group
int ngroups;
// Child thread groups of the current thread group
ThreadGroup groups[];
Copy the code

You can see this in the field properties

  • Threadgroups can have their own parent ThreadGroup
  • Threadgroups can have their own child thread groups
  • Threadgroups use an array of threads as storage containers

constructor

// Default constructor, private modifier, underlying call
private ThreadGroup(a) {     // called from C code
    	// The default thread group name is system
        this.name = "system";
    	// Maximum priority The default maximum priority of Thread is 10
        this.maxPriority = Thread.MAX_PRIORITY;
    	// Parent thread group is null
        this.parent = null;
    }
// The name of the receiving thread group
public ThreadGroup(String name) {
    	// Call the following constructor
        this(Thread.currentThread().getThreadGroup(), name);
    }
// Receives a parent thread group and the thread group name
public ThreadGroup(ThreadGroup parent, String name) {
    	// Call the following constructor
    	// The first parameter needs to be noticed
        this(checkParentAccess(parent), parent, name);
    }

// Receives a Void argument with the parent thread group and the thread group name
// Void is a placeholder
private ThreadGroup(Void unused, ThreadGroup parent, String name) {
    	// Assign a value to the current thread group name
        this.name = name;
    	// Maximum thread group priority is the maximum priority of the parent thread group
        this.maxPriority = parent.maxPriority;
    	// Daemon state is the daemon state of the parent thread group
        this.daemon = parent.daemon;
    	//vmAllowSuspension Sets the vmAllowSuspension of the parent thread group
        this.vmAllowSuspension = parent.vmAllowSuspension;
    	// Set the incoming thread group to the parent thread group
        this.parent = parent;
    	// The parent thread group adds the current thread to the child thread
        parent.add(this);
    }
Copy the code

You can see from the constructor

  • The default thread group name is System, and the default constructor is private and is called by C code
  • Parent thread group and thread group name can be specified during initialization
  • The Void argument above is nice, say it again

Method 4.

CheckParentAccess method

// Check thread group access
private static Void checkParentAccess(ThreadGroup parent) {
        parent.checkAccess();
        return null;
    }
Copy the code

GetName method

// Get the thread group name
public final String getName(a) {
        return name;
    }
Copy the code

GetParent method

// Get the parent thread group
public final ThreadGroup getParent(a) {
        if(parent ! =null)
            If the parent thread group is not null
            // Check the parent thread group access
            parent.checkAccess();
        return parent;
    }
Copy the code

GetMaxPriority method

// Get the maximum priority
public final int getMaxPriority(a) {
        return maxPriority;
    }
Copy the code

IsDaemon method

// Check if it is a daemon thread group
//true daemon thread group: If the last thread stops or the last thread group is destroyed, the current thread group is destroyed automatically
//false Common thread group: not destruct automatically
public final boolean isDaemon(a) {
        return daemon;
    }
Copy the code

IsDestroyed method

// Check whether the current thread group has been destroyed
public synchronized boolean isDestroyed(a) {
        return destroyed;
    }
Copy the code

SetDaemon method

// Sets whether the thread group is a daemon thread group
public final void setDaemon(boolean daemon) {
        checkAccess();
        this.daemon = daemon;
    }
Copy the code

SetMaxPriority method

// Set the maximum priority
public final void setMaxPriority(int pri) {
        int ngroupsSnapshot;
        ThreadGroup[] groupsSnapshot;
    	//============== sync code block ===========
        synchronized (this) {
            // Check access permissions
            checkAccess();
            // Check parameters
            if (pri < Thread.MIN_PRIORITY || pri > Thread.MAX_PRIORITY) {
                return;
            }
            // If the parent thread group is not null, the maximum priority of pri and parent thread group is the lowest
            // If the value is null, pri is used directlymaxPriority = (parent ! =null)? Math.min(pri, parent.maxPriority) : pri;// Copy the child thread group
            ngroupsSnapshot = ngroups;
            if(groups ! =null) {
                groupsSnapshot = Arrays.copyOf(groups, ngroupsSnapshot);
            } else {
                groupsSnapshot = null; }}//==============end===========
    	// Iterate to change the maximum priority of the child thread group
    	The maximum priority of the child thread group cannot be greater than the maximum priority of the parent thread group
        for (int i = 0; i < ngroupsSnapshot ; i++) { groupsSnapshot[i].setMaxPriority(pri); }}Copy the code

ParentOf method

// Tests whether the passed thread group is the parent of the current thread group
public final boolean parentOf(ThreadGroup g) {
    	// do a recursive search
        for(; g ! =null ; g = g.parent) {
            if (g == this) {
                // Find returns true
                return true; }}// Return false if not found
        return false;
    }
Copy the code

Method checkAccess

// Check access permissions (whether there is permission to modify this thread)
public final void checkAccess(a) {
    	// Get the security manager
        SecurityManager security = System.getSecurityManager();
        if(security ! =null) {
            // If the security manager is not null
            // Invoke the security manager's access check method
            security.checkAccess(this); }}Copy the code

ActiveCount method

// Returns the number of active threads in the current thread group and subthread group
// The value returned is an estimate, thread status is changing
public int activeCount(a) {
        int result;
        // Snapshot sub-group data so we don't hold this lock
        // while our children are computing.
        int ngroupsSnapshot;
        ThreadGroup[] groupsSnapshot;
    	//============= sync code block =================
        synchronized (this) {
            if (destroyed) {
                // If the thread group is destroyed, 0 is returned
                return 0;
            }
            Nthreads Specifies the number of active threads in the current thread group
            result = nthreads;
            // Copy the child thread group
            ngroupsSnapshot = ngroups;
            if(groups ! =null) {
                groupsSnapshot = Arrays.copyOf(groups, ngroupsSnapshot);
            } else {
                groupsSnapshot = null; }}//=============end=================
    	// Loop recursively over the number of active threads in the child thread group
        for (int i = 0 ; i < ngroupsSnapshot ; i++) {
            result += groupsSnapshot[i].activeCount();
        }
    	// Returns the count of active threads
        return result;
    }
Copy the code

Enumerate method

// Copies the active threads of the Thread group and its subgroups into the specified Thread array
public int enumerate(Thread list[]) {
    	// Check access permissions
        checkAccess();
    	// Call the following method
        return enumerate(list, 0.true);
    }
// Copies the active threads of the Thread group and its subgroups into the specified Thread array
private int enumerate(Thread list[], int n, boolean recurse) {
        int ngroupsSnapshot = 0;
        ThreadGroup[] groupsSnapshot = null;
    	//=========== sync code block ============
        synchronized (this) {
            if (destroyed) {
                // If the current thread group is destroyed, 0 is returned
                return 0;
            }
            int nt = nthreads;
            // What does n stand for? Keep n lengths, right? The default is 0
            if (nt > list.length - n) {
                nt = list.length - n;
            }
            // Loop to add active threads for the current thread group
            for (int i = 0; i < nt; i++) {
                if(threads[i].isAlive()) { list[n++] = threads[i]; }}// If recurse is true, add the child thread group's active thread
            if (recurse) {
                ngroupsSnapshot = ngroups;
                if(groups ! =null) {
                    groupsSnapshot = Arrays.copyOf(groups, ngroupsSnapshot);
                } else {
                    groupsSnapshot = null; }}}//===========end============
     // If RECURse is true, recurse recursively adds the active thread of the child thread group
        if (recurse) {
            for (int i = 0 ; i < ngroupsSnapshot ; i++) {
                n = groupsSnapshot[i].enumerate(list, n, true); }}return n;
    }
 // Copies the active threads of the Thread group and its subgroups into the specified Thread array
 // Resurse true Adds active thread to child group false Does not add child group thread
 public int enumerate(Thread list[], boolean recurse) {
     	// Check access permissions
        checkAccess();
     	// Call the above method
        return enumerate(list, 0, recurse);
    }
Copy the code
  • The thread group approach is similar

ActiveGroupCount method

// Returns the number of active thread groups for the current thread group and its child thread group
public int activeGroupCount(a) {
        int ngroupsSnapshot;
        ThreadGroup[] groupsSnapshot;
        synchronized (this) {
            if (destroyed) {
                return 0;
            }
            ngroupsSnapshot = ngroups;
            if(groups ! =null) {
                groupsSnapshot = Arrays.copyOf(groups, ngroupsSnapshot);
            } else {
                groupsSnapshot = null; }}// Assigns the number of current thread groups
        int n = ngroupsSnapshot;
    	// Loop recursively through the number of thread groups of child thread groups
        for (int i = 0 ; i < ngroupsSnapshot ; i++) {
            n += groupsSnapshot[i].activeGroupCount();
        }
        return n;
    }
Copy the code

Stop method

// Stops the threads of the thread group and all subthread groups
@Deprecated
    public final void stop(a) {
        // Stop the threads of the current thread group and all subthread groups
        if (stopOrSuspend(false))
            // Stop the current thread
            Thread.currentThread().stop();
    }
Copy the code

Suspend method

// Suspends the thread group and all child thread groups
@Deprecated
    @SuppressWarnings("deprecation")
    public final void suspend(a) {
        // Suspends the thread and all child thread groups
        if (stopOrSuspend(true))
            // Suspend the current thread
            Thread.currentThread().suspend();
    }
Copy the code

StopOrSuspend method

// Stops or suspends all threads in the current thread group and child thread groups
@SuppressWarnings("deprecation")
    private boolean stopOrSuspend(boolean suspend) {
        boolean suicide = false;
        // Get the current thread
        Thread us = Thread.currentThread();
        int ngroupsSnapshot;
        ThreadGroup[] groupsSnapshot = null;
        //=========== Synchronization method block =============
        synchronized (this) {
            // Check permissions
            checkAccess();
            for (int i = 0 ; i < nthreads ; i++) {
                if (threads[i]==us)
                    Suicide is set to true if the current traversal thread is the current calling thread
                    suicide = true;
                else if (suspend)
                    //suspend true suspends the thread
                    threads[i].suspend();
                else
                    //suspend False stops the thread
                    threads[i].stop();
            }

            ngroupsSnapshot = ngroups;
            if(groups ! =null) { groupsSnapshot = Arrays.copyOf(groups, ngroupsSnapshot); }}//===========end=============
        // Loop recursively walks over threads that stop or suspend all child thread groups
        for (int i = 0 ; i < ngroupsSnapshot ; i++)
            suicide = groupsSnapshot[i].stopOrSuspend(suspend) || suicide;

        return suicide;
    }
Copy the code

Interrupt method

// Interrupts the thread group and all child thread groups
public final void interrupt(a) {
        int ngroupsSnapshot;
        ThreadGroup[] groupsSnapshot;
        synchronized (this) {
            checkAccess();
            // Interrupts the thread of the current thread group
            for (int i = 0 ; i < nthreads ; i++) {
                threads[i].interrupt();
            }
            // Copy the child thread group
            ngroupsSnapshot = ngroups;
            if(groups ! =null) {
                groupsSnapshot = Arrays.copyOf(groups, ngroupsSnapshot);
            } else {
                groupsSnapshot = null; }}// Loop recursively interrupts the thread of the child thread group
        for (int i = 0; i < ngroupsSnapshot ; i++) { groupsSnapshot[i].interrupt(); }}Copy the code

Resume method

// Restore the threads of the thread group and all subthread groups
@Deprecated
    @SuppressWarnings("deprecation")
    public final void resume(a) {
        int ngroupsSnapshot;
        ThreadGroup[] groupsSnapshot;
        synchronized (this) {
            checkAccess();
            // Restore the thread of the current thread group
            for (int i = 0 ; i < nthreads ; i++) {
                threads[i].resume();
            }
            // Copy the child thread group
            ngroupsSnapshot = ngroups;
            if(groups ! =null) {
                groupsSnapshot = Arrays.copyOf(groups, ngroupsSnapshot);
            } else {
                groupsSnapshot = null; }}// Loop recursively to restore the thread of the child thread group
        for (int i = 0; i < ngroupsSnapshot ; i++) { groupsSnapshot[i].resume(); }}Copy the code

Destroy methods

// Destroy the thread group and all child thread groups
public final void destroy(a) {
        int ngroupsSnapshot;
        ThreadGroup[] groupsSnapshot;
        synchronized (this) {
            checkAccess();
            if (destroyed || (nthreads > 0)) {
                // Throw an exception if it has already been destroyed or there are still threads
                throw new IllegalThreadStateException();
            }
            // Copy the child thread group
            ngroupsSnapshot = ngroups;
            if(groups ! =null) {
                groupsSnapshot = Arrays.copyOf(groups, ngroupsSnapshot);
            } else {
                groupsSnapshot = null;
            }
            if(parent ! =null) {
                If the parent thread group is not null
                // Clear all data
                destroyed = true;
                ngroups = 0;
                groups = null;
                nthreads = 0;
                threads = null; }}// Loop recursively to destroy child thread groups
        for (int i = 0 ; i < ngroupsSnapshot ; i += 1) {
            groupsSnapshot[i].destroy();
        }
        if(parent ! =null) {
            If the parent thread group is not null
            // Remove yourself from the parent thread group
            parent.remove(this); }}Copy the code

The add method

// Add a child thread group
private final void add(ThreadGroup g){
        synchronized (this) {
            if (destroyed) {
                throw new IllegalThreadStateException();
            }
            if (groups == null) {
                // If the subthread group array is null
                // Creates an array of thread groups of size 4 by default
                groups = new ThreadGroup[4];
            } else if (ngroups == groups.length) {
                // If the thread group array is full, double it
                groups = Arrays.copyOf(groups, ngroups * 2);
            }
            / / assignment
            groups[ngroups] = g;
		    // Increase the number of thread groups by 1ngroups++; }}Copy the code

The remove method

// Remove a child thread group
private void remove(ThreadGroup g) {
        synchronized (this) {
            if (destroyed) {
                // If the current thread group is destroyed, it is returned directly
                return;
            }
            for (int i = 0 ; i < ngroups ; i++) {
                // The for loop iterates through the search
                if (groups[i] == g) {
                    // If found
                    // Reduce the number of child thread groups by 1
                    ngroups -= 1;
                    // Remove the current array of child threads
                    System.arraycopy(groups, i + 1, groups, i, ngroups - i);
                    // Set the last of the child thread array to NULL
                    groups[ngroups] = null;
                    // End the for loop
                    break; }}if (nthreads == 0) {
                // If the current number of threads is 0
                // Wake up all threads
                notifyAll();
            }
            if (daemon && (nthreads == 0) &&
                (nUnstartedThreads == 0) && (ngroups == 0))
            {
                // If it is a daemon thread group, and the number of threads and the array of child threads are 0
                // Destroy the current thread groupdestroy(); }}}// Remove the thread
private void remove(Thread t) {
        synchronized (this) {
            if (destroyed) {
                // If the thread group is destroyed, return directly
                return;
            }
            // The for loop iterates through the search
            for (int i = 0 ; i < nthreads ; i++) {
                if (threads[i] == t) {
                    // If found
                    // Override to remove the current thread
                    System.arraycopy(threads, i + 1, threads, i, --nthreads - i);
                    // Set the last of the child thread array to NULL
                    threads[nthreads] = null;
                    // End the for loop
                    break; }}}}Copy the code

AddUnstarted method

// Add a thread in the NEW state
void addUnstarted(a) {
        synchronized(this) {
            if (destroyed) {
                // If the current thread group is destroyed, an exception is thrown
                throw new IllegalThreadStateException();
            }
            / / nUnstartedThreads plus 1nUnstartedThreads++; }}Copy the code

The add method

// Add a thread
void add(Thread t) {
    	// Synchronize code blocks
        synchronized (this) {
            if (destroyed) {
                // Throw an exception if destroyed
                throw new IllegalThreadStateException();
            }
            if (threads == null) {
                // If the current thread array is null
                // Create an array of threads of size 4
                threads = new Thread[4];
            } else if (nthreads == threads.length) {
                // If the current thread array is full
                // Double the length
                threads = Arrays.copyOf(threads, nthreads * 2);
            }
            // Add a thread
            threads[nthreads] = t;
			// The number of threads increases by 1
            nthreads++;
            // The number of threads not started is reduced by 1nUnstartedThreads--; }}Copy the code

ThreadStartFailed method

// Failed to start the thread
void threadStartFailed(Thread t) {
    	// Roll back the state and retry later
        synchronized(this) {
            // Remove the thread from the array
            remove(t);
            // Count of unstarted threads + 1nUnstartedThreads++; }}Copy the code

ThreadTerminated method

// The thread terminates
void threadTerminated(Thread t) {
        synchronized (this) {
            // Remove the thread from the array
            remove(t);
            if (nthreads == 0) {
                // If the current active thread is 0
                // Wake up all threads
                notifyAll();
            }
            if (daemon && (nthreads == 0) &&
                (nUnstartedThreads == 0) && (ngroups == 0))
            {
                // If it is a daemon thread group, and the number of threads and the array of child threads are 0
                // Destroy the current thread groupdestroy(); }}}Copy the code

The list method

// Prints thread group information to standard output
public void list(a) {
    	// Call the following method
        list(System.out, 0);
    }
// Prints thread group information to standard output
void list(PrintStream out, int indent) {
        int ngroupsSnapshot;
        ThreadGroup[] groupsSnapshot;
        synchronized (this) {
            for (int j = 0 ; j < indent ; j++) {
                out.print("");
            }
            out.println(this);
            indent += 4;
            // Prints information about the current thread
            for (int i = 0 ; i < nthreads ; i++) {
                for (int j = 0 ; j < indent ; j++) {
                    out.print("");
                }
                out.println(threads[i]);
            }
            // Copy the child thread group
            ngroupsSnapshot = ngroups;
            if(groups ! =null) {
                groupsSnapshot = Arrays.copyOf(groups, ngroupsSnapshot);
            } else {
                groupsSnapshot = null; }}// Loop recursively to get the thread of the child thread
        for (int i = 0; i < ngroupsSnapshot ; i++) { groupsSnapshot[i].list(out, indent); }}Copy the code

UncaughtException method

// The thread in the current thread group did not catch the exception callback, which is invoked by the virtual machine
public void uncaughtException(Thread t, Throwable e) {
        if(parent ! =null) {
            // Parent thread group is not null
            // Go up
            parent.uncaughtException(t, e);
        } else {
            // Displays abnormal information
            Thread.UncaughtExceptionHandler ueh =
                Thread.getDefaultUncaughtExceptionHandler();
            if(ueh ! =null) {
                ueh.uncaughtException(t, e);
            } else if(! (einstanceof ThreadDeath)) {
                System.err.print("Exception in thread \""
                                 + t.getName() + "\" "); e.printStackTrace(System.err); }}}Copy the code

The toString method

// the toString method of ThreadGroup prints the class name and ThreadGroup name and maximum priority
public String toString(a) {
        return getClass().getName() + "[name=" + getName() + ",maxpri=" + maxPriority + "]";
    }
Copy the code