Thread - Thread Implementation and Thread Properties

Posted by Sonu Kapoor on Wed, 21 Aug 2019 11:41:45 +0200

Processes and threads

Process is the basic unit that can run independently and allocate resources in a computer system. It is composed of PCB (process control block), data segment and code segment. It is a basic unit that can run independently. The creation, scheduling and allocation of processes require large time and space overhead. Threads are introduced into the operating system, and threads are used as scheduling. The basic unit of allocation to improve the performance of multiprocessor systems

Threads are the smallest unit in which the operating system can schedule operations. Threads in the same process share all system resources in the process.

The difference between processes and threads:

  1. Each time a process is scheduled, context switching is needed to save the breakpoint information in PCB, which costs a lot. In thread scheduling, only a small number of registers need to be saved and set, and the switching cost is relatively small.
  2. As the basic unit of system resource allocation, process has certain resources, including disk and memory address space for storing program, data, I/O devices needed when it runs, open semaphores, etc. A set of registers and stacks that indicate the sequence of instructions to be executed, hold local variables, a few state parameters, return addresses, etc., allowing multiple threads to share memory address space and resources in the process.

Two ways to implement threads in java

In java, programs are allowed to run multiple threads concurrently, concurrency refers to the simultaneous occurrence of two or more events at the same time interval, and concurrency refers to the simultaneous execution of two or more events at the same time.

1. Inherit the Thread class and override the run() method

Thread represents the thread class. The run method is what we do when we start the thread. We should start the thread by using the start() method. To call the run method directly is equivalent to the ordinary method call. Next, we define a thread class to output 0 to 9 by inheriting the Thread class. Then we create two instances of the thread class in the main method. And start the thread, you can see that the thread execution is random. Thread scheduling details depend on the operating system. Preemptive thread scheduling gives each thread a time slice to run the thread. When the time slice is over, the system will save the status of the current thread, and then terminate the execution of the current thread and execute another thread. When the next time slice is over, the current thread of execution is terminated, and so on. Until all threads terminate.

 1 public class FirstThread extends Thread{
 2     @Override
 3     public void run() {
 4         for(int i = 0;i<10;i++) {
 5             System.out.println(Thread.currentThread().getName()+"Printing"+i);
 6         }
 7     }
 8 }
 9 public class FirstDemo {
10     public static void main(String[] args) {
11         Thread thread = new FirstThread();
12         Thread thread2 = new FirstThread();
13         thread.start();
14         thread2.start();
15     }    
16 }

2. Implementing Runnable Interface

The Thread class has a constructor whose parameter is a Runnable object, which can create a thread with a given Runnable object.

 1 public class FirstThread implements Runnable{
 2     @Override
 3     public void run() {
 4         for(int i = 0;i<10;i++) {
 5             System.out.println(Thread.currentThread().getName()+"Printing"+i);
 6         }
 7     }
 8 }
 9 public class FirstDemo {
10     public static void main(String[] args) {
11         Thread thread = new Thread(new FirstThread());
12         Thread thread2 = new Thread(new FirstThread());
13         thread.start();
14         thread2.start();
15     }    
16 }

Thread properties

Thread name (default Thread-serial number at thread initialization)

 1 private String name;
 2 
 3 // Set the name of the thread
 4 public final synchronized void setName(String name) {
 5         checkAccess();      // Check whether thread parameters are allowed to be changed
 6 
 7         if (name == null) {
 8             throw new NullPointerException("name cannot be null");
 9         }
10 
11         this.name = name;
12         if (threadStatus != 0) {      // Judging the state of threads
13             setNativeName(name);
14         }
15 }   
16 
17 // Get the name of the thread
18 public final String getName() {
19        return name;
20 }

Thread priority (default is parent thread priority)

 1 private int priority;
 2 
 3 public final static int MIN_PRIORITY = 1;  // Minimum priority of threads
 4 
 5 public final static int NORM_PRIORITY = 5; // Default priority of threads
 6 
 7 public final static int MAX_PRIORITY = 10; // Maximum priority of threads
 8 
 9 // Setting Thread Priority
10 public final void setPriority(int newPriority) {
11      ThreadGroup g;
12      checkAccess();      // Security check
13 
14      // Check whether the set priority is greater than the maximum priority or the minimum priority,If the parameter is thrown illegally 
15      if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) {
16          throw new IllegalArgumentException();
17      }
18 
19      // Get the current thread group
20      if((g = getThreadGroup()) != null) {
21         // If the current set priority is greater than its maximum priority on the thread group
22         if (newPriority > g.getMaxPriority()) {
23             // Set the priority of the current thread to the maximum priority of the current thread group
24             newPriority = g.getMaxPriority();
25         }
26         // Call local methods setPriority0 Setting Thread Priority
27         setPriority0(priority = newPriority);
28     }
29 }
30 
31 // Get the priority of the current thread
32 public final int getPriority() {
33     return priority;
34 }
35     

Is the thread a daemon thread (default is the value of the parent thread)

Daemon threads are threads that serve other threads. When only daemon threads are left in a program, the java virtual machine will quit the program. That is to say, daemon threads exist on the basis of user threads. The termination of user threads will cause the termination of daemon threads. Whatever the current state, daemon threads should be avoided when using daemon threads. A daemon-free thread accesses inherent resources, such as files, databases, etc. It interrupts in the middle of any operation.

 1 private boolean daemon;
 2 
 3 // Set whether the thread is a daemon thread
 4 public final void setDaemon(boolean on) {
 5     // Security check  
 6     checkAccess();
 7     
 8     // If the thread is active,Throws an exception that indicates that there is no proper state operation on the thread
 9     if (isAlive()) {
10         throw new IllegalThreadStateException();
11     }
12     // Set whether a thread is a daemon thread
13     daemon = on;
14 }
15 // Determine whether the current thread is active
16 public final native boolean isAlive();
17 
18 // Determine whether the current thread is a daemon thread
19 public final boolean isDaemon() {
20     return daemon;
21 }

Status of threads

The state of a thread is represented by an internal static enumeration class

 1 public enum State {
 2 
 3     NEW,      // New status
 4 
 5     RUNNABLE,      // Runnable state
 6 
 7     BLOCKED,        // Blocking state
 8 
 9     WAITING,     // Waiting state
10 
11     TIMED_WAITING,  // The state of waiting for a period of time.
12 
13     TERMINATED;  // Termination status
14 }
15    
16 // Gets the status of the current thread
17 public State getState() {
18         // get current thread state
19         return sun.misc.VM.toThreadState(threadStatus);
20 }

Uncaptured exception handlers for threads

The run method of a thread does not throw any checked exception. If an exception is thrown at runtime, but the exception is not caught and handled, the thread is about to terminate. At this point, the thread and exception will be used as parameters to call the method of the Uncaptured exception handler, which is a class that implements the UncaughtException Handler interface. UncaughtException is a static inner class of Thread, and there is only one method inside it: void uncaughtException (Thread, Throwable); this method will be called when the thread terminates due to an uncovered exception. The ThreadGroup class implements this interface. The Thread class has two variables of UncaughtException Handler interface, one is silent. The recognized processor (decorated with static) is used by all threads and the other is only used by the current thread. By default, both variables are null, and the Uncaptured exception processor used by the thread is the processor of the thread group.

 1 // For current threads
 2 private volatile UncaughtExceptionHandler uncaughtExceptionHandler;
 3 
 4 // Gets the Uncaptured exception handler for the current thread
 5 public UncaughtExceptionHandler getUncaughtExceptionHandler() {
 6     // If the current thread has no uncovered exception handler,Returns the processor of the thread group to which the thread belongs
 7     return uncaughtExceptionHandler != null ?
 8         uncaughtExceptionHandler : group;
 9 }
10 // Setting the Uncaptured exception handler for the current thread
11 public void setUncaughtExceptionHandler(UncaughtExceptionHandler eh) {
12     checkAccess();
13     uncaughtExceptionHandler = eh;
14 }
15 
16 // For all threads
17 private static volatile UncaughtExceptionHandler defaultUncaughtExceptionHandler;
18 
19 // Get the default Uncaptured exception handler
20 public static UncaughtExceptionHandler getDefaultUncaughtExceptionHandler(){
21     return defaultUncaughtExceptionHandler;
22 }
23 // Setting the default Uncaptured exception handler
24 public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh) {
25     
26     // Getting System Security Manager
27     SecurityManager sm = System.getSecurityManager();
28     if (sm != null) {
29         // Check whether requests with given permissions are allowed to execute,If not allowed,Throw out SecurityException abnormal
30         sm.checkPermission(
31 
32 // Create a thread that terminates suddenly because of an uncovered exception,Set the runtime permission object of the default handler to be used
33             new RuntimePermission("setDefaultUncaughtExceptionHandler")
34                 );
35     }
36     // Setting the default Uncaptured exception handler  
37     defaultUncaughtExceptionHandler = eh;
38 }
 1 // ThreadGroup Realization Thread.Uncaughtexception Source code parsing of interface
 2 public void uncaughtException(Thread t, Throwable e) {
 3     // If the thread group has a parent thread group,The processor that uses the parent thread group
 4     if (parent != null) {
 5         parent.uncaughtException(t, e);
 6     } else {
 7         
 8         // Get the default Uncaptured exception handler
 9         Thread.UncaughtExceptionHandler ueh =
10             Thread.getDefaultUncaughtExceptionHandler();
11         
12         // Use it if there is a default exception handler
13         if (ueh != null) {
14             ueh.uncaughtException(t, e);
15 
16         } 
17         // Otherwise, determine if the exception causing thread termination is ThreadDeath Subclasses,If it is,Do nothing,Responsible for exporting thread name and stack information to standard error stream,ThreadDeath yes
18         else if (!(e instanceof ThreadDeath)) {
19             System.err.print("Exception in thread \""
20                              + t.getName() + "\" ");
21             e.printStackTrace(System.err);
22         }
23     }
24 }        

Thread Group

Thread group is a set of unified managed threads. In addition to the initial thread group, each thread group has a parent thread group. Thread group can also contain other thread groups, allowing threads to access information about their own thread group, but not the parent thread group or any other thread group of their thread group. In this case, the thread groups created belong to the main thread group. There are two ways to construct the thread group

Thread Group Properties

 1     private final ThreadGroup parent; // Parent Thread Group,Once specified, non-modifiable
 2     String name; // Thread group name
 3     int maxPriority; // Maximum Priority of Thread Groups
 4     boolean destroyed; // Are Thread Groups Destroyed
 5     boolean daemon; // Is a thread group a daemon thread group?
 6     boolean vmAllowSuspension; // Automatic suspension of virtual machine
 7 
 8     int nUnstartedThreads = 0; // Number of Unstarted Threads in Thread Group
 9     int nthreads; // The number of threads contained in this thread group
10     Thread[] threads[]; // Threads included in this thread group
11 
12     int ngroups; // Subthread Group Counter
13     ThreadGroup[] groups; // Thread groups included in this thread group    
 1 Constructor call order from top to bottom
 2 
 3 //Use the specified thread group name to construct the thread group
 4 public ThreadGroup(String name) {
 5     // Gets the parent thread group of the current thread group
 6     this(Thread.currentThread().getThreadGroup(), name);
 7 }
 8 
 9 //Specify threads when creating a parent thread group,And the name is name Thread group
10 public ThreadGroup(ThreadGroup parent, String name) {
11     // Check the parent thread group
12     this(checkParentAccess(parent), parent, name);
13 }
14 
15 
16 //Check Thread Group Security
17 private static Void checkParentAccess(ThreadGroup parent) {
18      parent.checkAccess();
19      return null;
20 }
21 //Security check
22 public final void checkAccess() {
23      SecurityManager security = System.getSecurityManager();
24      if (security != null) {
25          security.checkAccess(this);
26      }
27 }
28 
29 private ThreadGroup(Void unused, ThreadGroup parent, String name) {
30     // Setting Thread Group Name
31     this.name = name;
32     // Maximum priority is the maximum priority of the parent thread group    
33     this.maxPriority = parent.maxPriority;
34     // Is it the daemon thread combination parent thread group consistent?
35     this.daemon = parent.daemon;
36     // Virtual Machine Parameters
37     this.vmAllowSuspension = parent.vmAllowSuspension;
38     this.parent = parent;
39     parent.add(this);
40 }
41 // Add the specified thread group
42 private final void add(ThreadGroup g) {
43     synchronized (this) {
44         // If the thread group has been destroyed,throw
45         if (destroyed) {
46             throw new IllegalThreadStateException();
47         }
48         // Determine whether the subthread array of this thread group is empty or full
49         // If empty,Create an array of sub-threads,Initial capacity is 4,Adds a specified thread group to the array,Counter plus one;
50         // If the subthread array is full,Array capacity doubled,Save the specified thread group into an array,Counter plus one
51         // If the subthread array is not full,Adds a specified thread group to the array,Counter plus one
52         if (groups == null) {
53             groups = new ThreadGroup[4];
54         } else if (ngroups == groups.length) {
55             groups = Arrays.copyOf(groups, ngroups * 2);
56         }
57         groups[ngroups] = g;
58         ngroups++;
59     }
60 }

Other methods

  1         // Remove the specified thread group
  2     private void remove(ThreadGroup g) {
  3         synchronized (this) {
  4             // Determine whether the thread group is dead
  5             if (destroyed) {
  6                 return;
  7             }
  8             // Loop traversal subthread array,Find the thread group to delete,If found,Subthread group counter minus one
  9             // Move the element behind the thread group element forward,Empty the last element,Break
 10             for (int i = 0; i < ngroups; i++) {
 11                 if (groups[i] == g) {
 12                     ngroups -= 1;
 13                     System.arraycopy(groups, i + 1, groups, i, ngroups - i);
 14                     groups[ngroups] = null;
 15                     break;
 16                 }
 17             }
 18 
 19             // Wake up all waiting threads on this object
 20             if (nthreads == 0) {
 21                 notifyAll();
 22             }
 23             // If this thread group satisfies the following conditions at the same time,Destroy the thread group and its subgroups
 24             // 1. Is the daemon thread group
 25             // 2. The number of threads included is 0
 26             // 3. The number of unstarted threads is 0
 27             // 4. The number of threads included is 0
 28             if (daemon && (nthreads == 0) && (nUnstartedThreads == 0) && (ngroups == 0)) {
 29                 destroy();
 30             }
 31         }
 32     }
 33 
 34     // Adds a specified thread to the thread group
 35     void add(Thread t) {
 36         synchronized (this) {
 37             if (destroyed) {
 38                 throw new IllegalThreadStateException();
 39             }
 40             if (threads == null) {
 41                 threads = new Thread[4];
 42             } else if (nthreads == threads.length) {
 43                 threads = Arrays.copyOf(threads, nthreads * 2);
 44             }
 45             threads[nthreads] = t;
 46             nthreads++;
 47             // To prevent thread groups from being destroyed,Decreasing number of unstarted threads
 48             nUnstartedThreads--;
 49         }
 50     }
 51 
 52     // Remove the specified thread
 53     private void remove(Thread t) {
 54         synchronized (this) {
 55             if (destroyed) {
 56                 return;
 57             }
 58             for (int i = 0; i < nthreads; i++) {
 59                 if (threads[i] == t) {
 60                     System.arraycopy(threads, i + 1, threads, i, --nthreads - i);
 61                     threads[nthreads] = null;
 62                     break;
 63                 }
 64             }
 65         }
 66     }
 67 
 68     // Get the name of the thread group
 69     public final String getName() {
 70         return name;
 71     }
 72 
 73     // Get the maximum priority of the thread group
 74     public final int getMaxPriority() {
 75         return maxPriority;
 76     }
 77 
 78     // Get the parent thread group of the thread group
 79     public final ThreadGroup getParent() {
 80         if (parent != null)
 81             parent.checkAccess();
 82         return parent;
 83     }
 84 
 85     // Determine whether the thread group is a daemon thread group
 86     public final boolean isDaemon() {
 87         return daemon;
 88     }
 89 
 90     // Determine whether the thread group is destroyed
 91     public synchronized boolean isDestroyed() {
 92         return destroyed;
 93     }
 94 
 95     // Set the maximum priority for this thread group
 96     public final void setMaxPriority(int pri) {
 97         int ngroupsSnapshot;
 98         ThreadGroup[] groupsSnapshot;
 99 
100         synchronized (this) {
101             checkAccess();
102             // Determine whether a given priority meets the requirements,Non-conforming direct return
103             if (pri < Thread.MIN_PRIORITY || pri > Thread.MAX_PRIORITY) {
104                 return;
105             }
106 
107             // If the current thread group does not have a parent thread group,The maximum priority is a given value
108             // Otherwise, determine the maximum priority and specified priority of the parent thread group,Take the minimum value as the maximum priority of the thread group
109             maxPriority = (parent != null) ? Math.min(pri, parent.maxPriority) : pri;
110 
111             // Get a snapshot of the thread subthread group(If it exists
112             ngroupsSnapshot = ngroups;
113             if (groups != null) {
114                 groupsSnapshot = Arrays.copyOf(groups, ngroupsSnapshot);
115             } else {
116                 groupsSnapshot = null;
117             }
118         }
119         // Traversing through all subthread groups of the thread group,Recursively sets the maximum priority to the specified value
120         for (int i = 0; i < ngroupsSnapshot; i++) {
121             groupsSnapshot[i].setMaxPriority(pri);
122         }
123     }
124 
125     // Set whether the thread group is a daemon thread
126     public final void setDaemon(boolean daemon) {
127         checkAccess();
128         this.daemon = daemon;
129     }
130 
131     // Test whether this thread group is the ancestor of the specified thread group
132     public final boolean parentOf(ThreadGroup g) {
133         for (; g != null; g = g.parent) {
134             if (g == this) {
135                 return true;
136             }
137         }
138         return false;
139     }
140 
141     // Destroy this thread group and its subgroups
142     public final void destroy() {
143         int ngroupsSnapshot;
144         ThreadGroup[] groupsSnapshot;
145         synchronized (this) {
146             checkAccess();
147             // If the thread group has been destroyed or there are active threads in the thread group,Throw an exception
148             if (destroyed || (nthreads > 0)) {
149                 throw new IllegalThreadStateException();
150             }
151             // Get a snapshot of the subthread group(If it exists)
152             ngroupsSnapshot = ngroups;
153             if (groups != null) {
154                 groupsSnapshot = Arrays.copyOf(groups, ngroupsSnapshot);
155             } else {
156                 groupsSnapshot = null;
157             }
158 
159             // If the thread group has a parent thread group,Empty all attributes
160             if (parent != null) {
161                 destroyed = true;
162                 ngroups = 0;
163                 groups = null;
164                 nthreads = 0;
165                 threads = null;
166             }
167         }
168         // Loop through subthread groups,Recursive processing for each subthread group
169         for (int i = 0; i < ngroupsSnapshot; i += 1) {
170             groupsSnapshot[i].destroy();
171         }
172 
173         // If a thread group has a parent thread group,Remove the thread group from the parent thread group
174         if (parent != null) {
175             parent.remove(this);
176         }
177     }
178 
179     // Get the number of threads active in this thread group
180     public int activeCount() {
181         int result;
182         int ngroupsSnapshot;
183         ThreadGroup[] groupsSnapshot;
184         synchronized (this) {
185             if (destroyed) {
186                 return 0;
187             }
188             result = nthreads;
189             ngroupsSnapshot = ngroups;
190             if (groups != null) {
191                 groupsSnapshot = Arrays.copyOf(groups, ngroupsSnapshot);
192             } else {
193                 groupsSnapshot = null;
194             }
195         }
196         for (int i = 0; i < ngroupsSnapshot; i++) {
197             result += groupsSnapshot[i].activeCount();
198         }
199         return result;
200     }
201 
202     // Get the number of threads that are active in this thread group
203     public int activeGroupCount() {
204         int ngroupsSnapshot;
205         ThreadGroup[] groupsSnapshot;
206         synchronized (this) {
207             if (destroyed) {
208                 return 0;
209             }
210             ngroupsSnapshot = ngroups;
211             if (groups != null) {
212                 groupsSnapshot = Arrays.copyOf(groups, ngroupsSnapshot);
213             } else {
214                 groupsSnapshot = null;
215             }
216         }
217         int n = ngroupsSnapshot;
218         for (int i = 0; i < ngroupsSnapshot; i++) {
219             n += groupsSnapshot[i].activeGroupCount();
220         }
221         return n;
222     }
223 
224     // Export information about this thread group to the standard output stream
225     public void list() {
226         list(System.out, 0);
227     }
228 
229     void list(PrintStream out, int indent) {
230         int ngroupsSnapshot;
231         ThreadGroup[] groupsSnapshot;
232         synchronized (this) {
233             for (int j = 0; j < indent; j++) {
234                 out.print(" ");
235             }
236             out.println(this);
237             indent += 4;
238             for (int i = 0; i < nthreads; i++) {
239                 for (int j = 0; j < indent; j++) {
240                     out.print(" ");
241                 }
242                 out.println(threads[i]);
243             }
244             ngroupsSnapshot = ngroups;
245             if (groups != null) {
246                 groupsSnapshot = Arrays.copyOf(groups, ngroupsSnapshot);
247             } else {
248                 groupsSnapshot = null;
249             }
250         }
251         for (int i = 0; i < ngroupsSnapshot; i++) {
252             groupsSnapshot[i].list(out, indent);
253         }
254     }
255 
256     // Returns a string description of this class:Class name+Thread group name+Maximum priority
257     public String toString() {
258         return getClass().getName() + "[name=" + getName() + ",maxpri=" + maxPriority + "]";
259     }
260 
261     // All threads and sub-threads in interrupt threads group
262     public final void interrupt() {
263         int ngroupsSnapshot;
264         ThreadGroup[] groupsSnapshot;
265         synchronized (this) {
266             checkAccess();
267             // Interrupt the included thread
268             for (int i = 0; i < nthreads; i++) {
269                 threads[i].interrupt();
270             }
271             ngroupsSnapshot = ngroups;
272             if (groups != null) {
273                 groupsSnapshot = Arrays.copyOf(groups, ngroupsSnapshot);
274             } else {
275                 groupsSnapshot = null;
276             }
277         }
278         // Traversing subthread groups,Recursive processing of each subthread group
279         for (int i = 0; i < ngroupsSnapshot; i++) {
280             groupsSnapshot[i].interrupt();
281         }
282     }
283 
284     // Copies all active threads of the thread group into the specified array. If a second parameter exists,The second parameter is true Represents active threads that contain subgroups,The default number of active threads in a subgroup,
285     // When a given array is insufficient to accommodate the number of active threads in that thread group,Ignore additional threads,therefore,Better call activeCount Method to determine if less than list Length
286     public int enumerate(Thread list[]) {
287         checkAccess();
288         return enumerate(list, 0, true);
289     }
290 
291     public int enumerate(Thread list[], boolean recurse) {
292         checkAccess();
293         return enumerate(list, 0, recurse);
294     }
295 
296     private int enumerate(Thread list[], int n, boolean recurse);
297 
298     // Copies all active subgroups of the thread group into the specified array. If a second parameter exists,The second parameter is true Represents an active subgroup in a containing subgroup,Default contains all active subgroups in subgroups,
299     // When the given array is insufficient to accommodate the active subarray of the thread group,Ignore additional subgroups,therefore,Better call activeGroupCount Method to determine if less than list Length
300 
301     public int enumerate(ThreadGroup list[]) {
302         checkAccess();
303         return enumerate(list, 0, true);
304     }
305 
306     public int enumerate(ThreadGroup list[], boolean recurse) {
307         checkAccess();
308         return enumerate(list, 0, recurse);
309     }
310 
311     private int enumerate(ThreadGroup list[], int n, boolean recurse);
312 
313     // allow Java The virtual machine is suspended because of insufficient memory
314     @Deprecated
315     public boolean allowThreadSuspension(boolean b);
316 
317     // Stop all threads in this thread group,Unsafe
318     @Deprecated
319     public final void stop();
320 
321     // Suspend all threads in this thread group. Easy to cause deadlock
322     @Deprecated
323     public final void suspend();
324 
325     // Continue all threads in this thread group. Easy to cause deadlock
326     @Deprecated
327     public final void resume();
328 
329 }

Thread threads

  1 // Public constructors essentially call four parameters first init Method,Then call the private of six parameters init Method to construct Thread objects
  2 
  3 public Thread() {
  4     // Set the name of the thread when calling a parametric construct,Then call the private of the four parameters init Method,from init Method to call six parameters init Method
  5     init(null, null, "Thread-" + nextThreadNum(), 0);
  6 }
  7 
  8 // Constructing a new Thread object,Use the specified runtime object
  9 public Thread(Runnable target) {
 10     // Set the name of the thread,Calling four parameters init Method,from init Method to call six parameters init Method
 11     init(null, target, "Thread-" + nextThreadNum(), 0);
 12 }
 13 
 14 // Construct a specified thread group,Using the specified running object Thread object
 15 public Thread(ThreadGroup group, Runnable target) {
 16     init(group, target, "Thread-" + nextThreadNum(), 0);
 17 }
 18 
 19 // Constructing a specified thread name Thread object
 20 public Thread(String name) {
 21     init(null, null, name, 0);
 22 }
 23 
 24 // Constructing a specified thread group and name Thread object
 25 public Thread(ThreadGroup group, String name) {
 26     init(group, null, name, 0);
 27 }
 28 
 29 // Construct an object with the specified running object and name Thread object
 30 public Thread(Runnable target, String name) {
 31     init(null, target, name, 0);
 32 }
 33 
 34 // Construct a group of specified threads,Running object and name Thread object
 35 public Thread(ThreadGroup group, Runnable target, String name) {
 36     init(group, target, name, 0);
 37 }
 38 
 39 // Construct a group of specified threads,Running object,Name and stack size Thread object
 40 public Thread(ThreadGroup group, Runnable target, String name,
 41               long stackSize) {
 42     init(group, target, name, stackSize);
 43 }
 44 
 45 // This constructor is not public,He will create a
 46 Thread(Runnable target, AccessControlContext acc) {
 47         init(null, target, "Thread-" + nextThreadNum(), 0, acc, false);
 48 }
 49 
 50 // The public constructor calls this method first
 51 private void init(ThreadGroup g, Runnable target, String name,
 52                       long stackSize) {
 53         init(g, target, name, stackSize, null, true);
 54 }
 55 
 56 private void init(ThreadGroup g, Runnable target, String name, long stackSize, AccessControlContext acc,boolean inheritThreadLocals) {
 57         // If the given thread name is null Throw a null pointer exception
 58     if (name == null) {
 59     throw new NullPointerException("name cannot be null");
 60     }
 61         // Set the thread name
 62     this.name = name;
 63         // Get the parent thread
 64     Thread parent = currentThread();
 65         // Getting the Security Manager
 66     SecurityManager security = System.getSecurityManager();
 67         
 68         // If the thread group where the thread is not specified
 69     if (g == null) {
 70             // If the security manager exists,Returns the thread group of the current thread using the security manager method
 71         if (security != null) {
 72                 g = security.getThreadGroup();
 73             }
 74         
 75             // If the thread group still does not belong to it,Use the thread group of the parent thread as the thread group of that thread     
 76         if (g == null) {
 77          g = parent.getThreadGroup();
 78         }
 79          }
 80         // Determine whether the current thread has permission to modify this g Thread group,The time of this method ThreadGroup Of
 81         g.checkAccess();
 82 
 83         // Check for permissions
 84         if (security != null) {
 85             // Verify that the instance can be constructed
 86             if (isCCLOverridden(getClass())) {
 87               security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);// Verify that there are specified run-time permissions 
 88             }
 89         }
 90          // Increase the number of threads that are not started in the thread group.
 91         g.addUnstarted();
 92 
 93         // Setting Thread Related Properties,Get the related attributes of the parent thread as the related attributes of the thread(If not specified)
 94         this.group = g;
 95         this.daemon = parent.isDaemon();
 96         this.priority = parent.getPriority();
 97         if (security == null || isCCLOverridden(parent.getClass()))
 98             this.contextClassLoader = parent.getContextClassLoader();
 99         else
100             this.contextClassLoader = parent.contextClassLoader;
101         this.inheritedAccessControlContext =
102                 acc != null ? acc : AccessController.getContext();
103         this.target = target;
104         setPriority(priority);
105         if (inheritThreadLocals && parent.inheritableThreadLocals != null)
106             this.inheritableThreadLocals =
107                 ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
108         this.stackSize = stackSize;
109         tid = nextThreadID();
110 }

Class diagrams between ThreadGroup,Thread,Thread.State,Thread.UncaughtException

Topics: Java snapshot less