1. Runnable interface source code:
1 public interface Runnable {2 public abstract void run();3 }
2. inheritance between the Thread class and the Runnable interface
1 public class Thread implements Runnable{2 3 }
The Runnable interface has only one run () method. The Thread class implements the Runnable interface. Therefore, the Thread class also implements the Runnable interface.
3. Constructor
1 public Thread() {2 init(null, null, "Thread-" + nextThreadNum(), 0);3 }
1 public Thread(Runnable target) {2 init(null, target, "Thread-" + nextThreadNum(), 0);3 }
1 public Thread(ThreadGroup group, Runnable target) {2 init(group, target, "Thread-" + nextThreadNum(), 0);3 }
1 public Thread (String name) {2 init (null, null, name, 0); 3}
There are other constructor methods, which are omitted here...
The third parameter here is to set the Thread name. From the code below, we can see that the rule for generating the name is: "Thread-" and the number of created threads (number of threads ).
Continue to view the init method:
1/** 2 * Initializes a Thread. 3*4 * @ param g the Thread group 5 * @ param target the object whose run () method gets called 6 * @ param name the name of the new Thread 7 * @ param stackSize the desired stack size for the new thread, or 8 * zero to indicate that this parameter is to be ignored. 9 */
// ThreadGroup: A thread group is a set of threads. In addition, thread groups can contain other thread groups. A thread group is a tree in which each thread group has a parent thread group except the initial thread group.10 private void init (ThreadGroup g, Runnable target, String name, 11 long stackSize) {12 Thread parent = currentThread (); 13 SecurityManager security = System. getSecurityManager (); 14 if (g = null) {15/* Determine if it's an applet or not */16 17/* If there is a security manager, ask the security manager18 what to do. */19 if (security! = Null) {20g = security. getThreadGroup (); 21} 22 23/* If the security doesn't have a strong opinion of the matter24 use the parent thread group. */25 if (g = null) {26g = parent. getThreadGroup (); 27} 28} 29 30/* checkAccess regardless of whether or not threadgroup is31 explicitly passed in. */32g. checkAccess (); 33 34/* 35 * Do we have the required permissions? 36 */37 if (security! = Null) {38 if (isCCLOverridden (getClass () {39 security. checkPermission (SUBCLASS_IMPLEMENTATION_PERMISSION); 40} 41} 42 43 44g. addUnstarted (); 45 46 this. group = g;
//Each thread has a priority. The execution of a high-priority thread takes precedence over that of a low-priority thread. Each thread can or cannot be marked as a daemon. When the code running in a thread creates a newThreadObject, the initial priority of the new thread is set to the priority of the Creation thread, and when and only when the creation thread is a daemon thread, the new thread is the daemon.
47 this.daemon = parent.isDaemon();48 this.priority = parent.getPriority();49 this.name = name.toCharArray();50 if (security == null || isCCLOverridden(parent.getClass()))51 this.contextClassLoader = parent.getContextClassLoader();52 else53 this.contextClassLoader = parent.contextClassLoader;54 this.inheritedAccessControlContext = AccessController.getContext();55 this.target = target;56 setPriority(priority);57 if (parent.inheritableThreadLocals != null)58 this.inheritableThreadLocals =59 ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);60 /* Stash the specified stack size in case the VM cares */61 this.stackSize = stackSize;62 63 /* Set thread ID */64 tid = nextThreadID();65 }
The initialization parameter specifies whether it is a daemon thread, priority, and initialization name.
4. Implementation of the Thread start method:
1 public synchronized void start() { 2 /** 3 * This method is not invoked for the main method thread or "system" 4 * group threads created/set up by the VM. Any new functionality added 5 * to this method in the future may have to also be added to the VM. 6 * 7 * A zero status value corresponds to state "NEW". 8 */ 9 if (threadStatus != 0)10 throw new IllegalThreadStateException();11 group.add(this);12 start0();13 if (stopBeforeStart) {14 stop0(throwableFromStop);15 }16 }
The main method here is start0; view its implementation:
1 private native void start0();
The local call is used to initialize the system resources required by the thread through the C code. It can be seen that the underlying implementation of the thread is completed through the C code.
4. Implementation of the Thread run Method
1 public void run() {2 if (target != null) {3 target.run();4 }5 }
Here, the target actually needs to save a reference to the implementation of a Runnable interface:
1 private Runnable target;
Therefore, when using the inherited Thread to create a Thread class, you need to override the run method, because the default run method does nothing.
When we use the Runnable interface to implement the Thread class, to start the Thread, We need to initialize the Thread class instance to a Thread, and actually execute the following constructor:
1 public Thread(Runnable target) {2 init(null, target, "Thread-" + nextThreadNum(), 0);3 }
Saves the reference of the thread class to the target. In this way, when the run method of Thread is called, the target will not be empty, but will continue to call the run method of target. Therefore, we need to implement the Runnable run method. In this way, the run method in the Runnable implementation class is called through the run method of Thread.
This is also the reason why the Thread class implemented by the Runnable interface needs to be started in this way.