preface

Java Thread is the use of Thread class implementation, Thread in the beginning to learn Java when the school, also used in practice, but has not seen it from the source point of view, today from the source point of view, learning Java Thread again, after the practice of Thread is more handy.

Start with comments

I believe that students who have read the JDK source code can feel the JDK source code has a very detailed annotations, read a class source code should first look at the annotations to its introduction, annotations will not paste the original, the following is my summary of it:

  • Threads are threads of execution in a program, and the Java Virtual Machine allows applications to allow multiple threads of execution simultaneously

  • Every thread has a concept of priority, and a thread with a higher priority executes before a thread with a lower priority

  • Each thread can be set as a daemon thread

  • When code running in a Thread creates a new Thread object, the new Thread has the same priority as the Thread that created it

  • When a Java virtual machine is started, a thread called main is started, which has no daemon thread, and the main thread continues to execute until it is sent

    • RuntimeClass exit methodexitIs called and the security manager allows an exit operation
    • All non-daemon threads are dead, orrunMethod completes and returns results normally, orrunMethod throws an exception
  • The first way to create a Thread is to inherit the Thread class and override the run method

    // Define the thread class
    class PrimeThread extends Thread {
          long minPrime;
          PrimeThread(long minPrime) {
              this.minPrime = minPrime;
          }
          public void run(a) {
              // compute primes larger than minPrime  .  .  .}}// Start the thread
    PrimeThread p = new PrimeThread(143);
    p.start();
    Copy the code
  • Second way to create a thread: Implement the Runnable interface and override the run method. Because of Java’s single-inheritance limitations, it is often more flexible to create threads this way

    // Define a thread
     class PrimeRun implements Runnable {
          long minPrime;
          PrimeRun(long minPrime) {
              this.minPrime = minPrime;
          }
          public void run(a) {
              // compute primes larger than minPrime  .  .  .}}// Start the thread
    PrimeRun p = new PrimeRun(143);
    new Thread(p).start();
    Copy the code
  • A thread can be given a name when it is created. If no name is specified, a name is automatically generated for it

  • Unless otherwise noted, passing a null argument to a constructor or method in the Thread class will result in a NullPointerException being thrown

Common attributes of Thread

To read a Java class, start with what properties it has:

// Thread name. You can specify a thread name when creating a thread
private volatile String name;

// Thread priority. You can set the thread priority
private int priority;

// Threads can be configured to be daemons. Default is false
private boolean daemon = false;

// Finally execute the thread task 'Runnable'
private Runnable target;

// A class that describes thread groups
private ThreadGroup group;

// The context ClassLoader for this thread
private ClassLoader contextClassLoader;

// The number of all initialized threads, used to automatically number anonymous threads. When no thread name is specified, it is automatically numbered
private static int threadInitNumber;

// The stack size requested by this thread, or 0 if not specified by the creator. The virtual machine can do whatever it likes with this number. Some virtual machines ignore it.
private long stackSize;

/ / thread id
private long tid;

// Used to generate the thread ID
private static long threadSeqNumber;

// Thread status
private volatile int threadStatus = 0;

// The lowest priority a thread can have
public final static int MIN_PRIORITY = 1;

// The default priority assigned to threads.
public final static int NORM_PRIORITY = 5;

// The maximum priority a thread can have
public final static int MAX_PRIORITY = 10;
Copy the code

All attribute names are very semantic, in fact, you can guess what it is based on the name, it is not difficult ~ ~

Thread constructor

Now that we know about the properties, how are Thread instances constructed? Here’s a preview of how many constructors it has:

Each constructor calls a private method called init. Init has two overloads, and its core method is as follows:

   /**
     * Initializes a Thread.
     *
     * @paramG thread group *@paramTarget Object * of the 'run()' method that ultimately executes the task@paramName Name of the new thread *@paramStackSize the stackSize required by the new thread, or 0 indicates that this parameter * is to be ignored@paramAcc to inherit AccessControlContext, if is null, then for the AccessController. GetContext () *@paramInheritThreadLocals, if true, inherits the inheritable thread-local initial value */ from the constructor thread
    private void init(ThreadGroup g, Runnable target, String name,
                      long stackSize, AccessControlContext acc,
                      boolean inheritThreadLocals) {
        // If the thread name is null, throw a null pointer exception
        if (name == null) {
            throw new NullPointerException("name cannot be null");
        }
        // Initialize the thread name of the current thread object
        this.name = name;
        // Get the currently executing thread as the parent thread
        Thread parent = currentThread();
        // Get the system security manager
        SecurityManager security = System.getSecurityManager();
        // If the thread group is empty
        if (g == null) {
            // If security manager is not empty
            if(security ! =null) {
                // Get the thread group in SecurityManager
                g = security.getThreadGroup();
            }
            // If the thread group is still empty
            if (g == null) {
                // the parent thread group is usedg = parent.getThreadGroup(); }}// Check security permissions
        g.checkAccess();

        // Use security manager to check for permissions
        if(security ! =null) {
            if(isCCLOverridden(getClass())) { security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION); }}// The number of threads marked as not started in the thread group +1, where the method is synchronized to prevent thread safety issues
        g.addUnstarted();
        
        // Initialize the thread group of the current thread object
        this.group = g;
        // Initializes the daemon property of the current thread object. Note that the initialization is consistent with the parent thread
        this.daemon = parent.isDaemon();
        // Initialize the thread priority property of the current thread object. Note that the initialization is consistent with the parent thread
        this.priority = parent.getPriority();
        // Initializes the classloader
        if (security == null || isCCLOverridden(parent.getClass()))
            this.contextClassLoader = parent.getContextClassLoader();
        else
            this.contextClassLoader = parent.contextClassLoader;
        this.inheritedAccessControlContext = acc ! =null ? acc : AccessController.getContext();
        // Initializes the final execution task of the current thread object
        this.target = target;
        // The priority field of the thread is processed
        setPriority(priority);
        if(inheritThreadLocals && parent.inheritableThreadLocals ! =null)
            this.inheritableThreadLocals =
                ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
        // Initializes the stack size of the current thread object
        this.stackSize = stackSize;

        // initializes the thread ID of the current thread object. This method is synchronous and is actually threadSeqNumber++ internally
        tid = nextThreadID();
    }
Copy the code

Another override init private method that actually calls the above init method internally:

private void init(ThreadGroup g, Runnable target, String name,
                      long stackSize) {
        init(g, target, name, stackSize, null.true);
    }
Copy the code

Let’s look at all the constructors:

  1. Null construction method

     public Thread(a) {
            init(null.null."Thread-" + nextThreadNum(), 0);
        }
    Copy the code

    NextThreadNum () is a synchronous method, and maintains a static attribute indicating the number of threads initialized +1:

     private static int threadInitNumber;
        private static synchronized int nextThreadNum(a) {
            return threadInitNumber++;
        }
    Copy the code
  2. Custom constructor of the Runnable object that executes the task

    public Thread(Runnable target) {
        init(null, target, "Thread-" + nextThreadNum(), 0);
    }
    Copy the code

    The difference from the first constructor is that Runnable objects can be customized

  3. Customize the constructor of the Runnable and AccessControlContext objects to execute the task

     Thread(Runnable target, AccessControlContext acc) {
        init(null, target, "Thread-" + nextThreadNum(), 0, acc, false);
    }
    Copy the code
  4. Custom ThreadGroup ThreadGroup and task Runnable object constructor

    public Thread(ThreadGroup group, Runnable target) {
        init(group, target, "Thread-" + nextThreadNum(), 0);
    }
    Copy the code
  5. Constructor for custom thread name name

     public Thread(String name) {
        init(null.null, name, 0);
    }
    Copy the code
  6. Constructor for custom ThreadGroup ThreadGroup and thread name name

     public Thread(ThreadGroup group, String name) {
        init(group, null, name, 0);
    }
    Copy the code
  7. Customize the constructor for the Runnable object and the thread name name to execute the task

     public Thread(Runnable target, String name) {
        init(null, target, name, 0);
    }
    Copy the code
  8. Custom ThreadGroup ThreadGroup and thread name name and execution task Runnable object constructor

      public Thread(ThreadGroup group, Runnable target, String name) {
        init(group, target, name, 0);
    }
    Copy the code
  9. All attributes are custom constructors

      public Thread(ThreadGroup group, Runnable target, String name,
                  long stackSize) {
        init(group, target, name, stackSize);
    }
    Copy the code

Thread provides a very flexible overloaded constructor that allows developers to customize Thread objects with various parameters.

Commonly used method

Here are some of the more common methods, but let’s ignore some of the native methods that exist in Thread

Setting the thread name

To prevent Thread safety problems, you can manually call the Thread instance method to set the name. You can also pass the Thread name in the constructor when constructing the Thread. We usually set the name when constructing the parameter

   public final synchronized void setName(String name) {    // Check security permissionscheckAccess();    // Throw a null pointer exception if the parameter is empty
          if (name == null) {
              throw new NullPointerException("name cannot be null");
          }
  	  // Sets the name of the current thread object
          this.name = name;
          if(threadStatus ! =0) { setNativeName(name); }}Copy the code

Get thread name

Internally returns the name property of the current thread object

  public final String getName(a) {
        return name;
    }
Copy the code

Starting a thread

public synchronized void start(a) {
        // If it is not a newly created thread, throw an exception
        if(threadStatus ! =0)
            throw new IllegalThreadStateException();

        // Notify the thread group that the current thread is about to be started. The number of currently started threads in the thread group is +1, and the number of unstarted threads is -1
        group.add(this);
        
        // Start identifier
        boolean started = false;
        try {
            // Call a local method directly to start the thread
            start0();
            // Set the startup identifier to successful startup
            started = true;
        } finally {
            try {
                // If start fails
                if(! started) {// Remove the number of threads currently started and the number of failed threads +1 from the thread group
                    group.threadStartFailed(this); }}catch (Throwable ignore) {
                /* do nothing. If start0 threw a Throwable then it will be passed up the call stack */}}}Copy the code

Thred’s run () method is called from the Java virtual machine (JVM). The Thread class implements the Runnable interface and overwrites the run method:

 @Override
    public void run(a) {
        // If the Runnable object currently executing the task is not empty, call its run method
        if(target ! =null) { target.run(); }}Copy the code

Thread can be used in two ways:

  • inheritanceThreadClass, rewriterunMethod, then the execution is directrunMethod logic is not usedtarget.run();
  • implementationRunnableInterface, overriderunMethod, becauseJavaThe single-inheritance limit for thread creation is usually more flexible in this way, where the real execution logic is left to customizationRunnableTo achieve

Setting up the daemon thread

The essence is to set daemon properties

public final void setDaemon(boolean on) {
        // Check whether you have security permissions
        checkAccess();
        // A local method that tests whether the thread is alive. , a thread is active if it has been started and is not dead
        if (isAlive()) {
            If the daemon thread is set up after the program is started, an exception will be thrown
            throw new IllegalThreadStateException();
        }
        // Sets the current daemon thread properties
        daemon = on;
    }
Copy the code

Determines whether the thread is a daemon thread

 public final boolean isDaemon(a) {
        // Directly returns the daemon property of the current object
        return daemon;
    }
Copy the code

Thread state

Let’s start with a thread state graph:

Get thread status:

 public State getState(a) {
        // Implemented by a virtual machine, to get the state of the current thread
        return sun.misc.VM.toThreadState(threadStatus);
    }
Copy the code

Thread State consists mainly of the internal enumeration class State:

  public enum State {
      
        NEW,

      
        RUNNABLE,

      
        BLOCKED,

       
        WAITING,

       
        TIMED_WAITING,

       
        TERMINATED;
    }
Copy the code
  • NEW: the thread has just been created and has not been started
  • RUNNABLE: The thread executing in the Java VIRTUAL machine is in this state
  • BLOCKED: the state in which a thread is BLOCKED awaiting a monitor lock, such as when it is encountered during executionsynchronizedBlock synchronization enters this state, where the thread suspends execution until the requested lock is acquired
  • WAITING: a thread in this state that is WAITING indefinitely for another thread to perform a particular operation
    • Threads waiting with wait() are waiting for notify()
    • Threads waiting through the join() method wait for the destination thread to terminate
  • TIMED_WAITING: Waiting for another thread to execute an action until the thread with the specified waiting time is in this state
    • With wait(), which carries a timeout, the waiting thread is waiting for notify()
    • With the join() method, which carries a timeout, waiting threads wait for the destination thread to terminate
  • TERMINATED: The TERMINATED thread is in this state and cannot return to the RUNNABLE state

Thread to sleep

This is a static local method that causes the currently executing thread sleep to suspend execution of millis for milliseconds and throws InterruptedException when sleep is interrupted

    /**
     * Causes the currently executing thread to sleep (temporarily cease
     * execution) for the specified number of milliseconds, subject to
     * the precision and accuracy of system timers and schedulers. The thread
     * does not lose ownership of any monitors.
     *
     * @param  millis
     *         the length of time to sleep in milliseconds
     *
     * @throws  IllegalArgumentException
     *          if the value of {@code millis} is negative
     *
     * @throws  InterruptedException
     *          if any thread has interrupted the current thread. The
     *          <i>interrupted status</i> of the current thread is
     *          cleared when this exception is thrown.
     */
    public static native void sleep(long millis) throws InterruptedException;
Copy the code

Check whether the thread is alive

Local method that tests whether the thread is alive. A thread is active if it has been started and is not dead.

    /**
     * Tests if this thread is alive. A thread is alive if it has
     * been started and has not yet died.
     *
     * @return  <code>true</code> if this thread is alive;
     *          <code>false</code> otherwise.
     */
    public final native boolean isAlive(a);
Copy the code

Thread priority

  • Set the thread priority
    /**
     * Changes the priority of this thread.
     * <p>
     * First the <code>checkAccess</code> method of this thread is called
     * with no arguments. This may result in throwing a
     * <code>SecurityException</code>.
     * <p>
     * Otherwise, the priority of this thread is set to the smaller of
     * the specified <code>newPriority</code> and the maximum permitted
     * priority of the thread's thread group.
     *
     * @param newPriority priority to set this thread to
     * @exception  IllegalArgumentException  If the priority is not in the
     *               range <code>MIN_PRIORITY</code> to
     *               <code>MAX_PRIORITY</code>.
     * @exception  SecurityException  if the current thread cannot modify
     *               this thread.
     * @see        #getPriority
     * @see        #checkAccess()
     * @see        #getThreadGroup()
     * @see        #MAX_PRIORITY
     * @see        #MIN_PRIORITY
     * @see        ThreadGroup#getMaxPriority()
     */
    public final void setPriority(int newPriority) {
        / / thread group
        ThreadGroup g;
        // Check security permissions
        checkAccess();
        // Check the range of priority parameters
        if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) {
            throw new IllegalArgumentException();
        }
        if((g = getThreadGroup()) ! =null) {
            // If the priority parameter is greater than the maximum thread group maximum thread priority
            if (newPriority > g.getMaxPriority()) {
                // The priority data of the thread group is used
                newPriority = g.getMaxPriority();
            }
            // Call the local set thread priority methodsetPriority0(priority = newPriority); }}Copy the code

Thread the interrupt

There is an instance of the stop() method that can force a thread to terminate, but this method is so violent that it has been labeled obsolete and should not be used by programmers because forcing a thread to terminate can cause data inconsistencies.

There are three ways to interrupt a thread:

// instance method to notify the thread of interruption and set the flag bit
 public void interrupt(a){}
 // Static method, check the current thread interrupt state, at the same time will clear the current thread interrupt flag state
 public static boolean interrupted(a){}
 // check whether the current thread is interrupted
 public boolean isInterrupted(a){}
Copy the code

The interrupt() method parses

/**
     * Interrupts this thread.
     *
     * <p> Unless the current thread is interrupting itself, which is
     * always permitted, the {@link #checkAccess() checkAccess} method
     * of this thread is invoked, which may cause a {@link
     * SecurityException} to be thrown.
     *
     * <p> If this thread is blocked in an invocation of the {@link
     * Object#wait() wait()}, {@link Object#wait(long) wait(long)}, or {@link
     * Object#wait(long, int) wait(long, int)} methods of the {@link Object}
     * class, or of the {@link #join()}, {@link #join(long)}, {@link
     * #join(long, int)}, {@link #sleep(long)}, or {@link #sleep(long, int)},
     * methods of this class, then its interrupt status will be cleared and it
     * will receive an {@link InterruptedException}.
     *
     * <p> If this thread is blocked in an I/O operation upon an {@link
     * java.nio.channels.InterruptibleChannel InterruptibleChannel}
     * then the channel will be closed, the thread's interrupt
     * status will be set, and the thread will receive a {@link
     * java.nio.channels.ClosedByInterruptException}.
     *
     * <p> If this thread is blocked in a {@link java.nio.channels.Selector}
     * then the thread's interrupt status will be set and it will return
     * immediately from the selection operation, possibly with a non-zero
     * value, just as if the selector's {@link
     * java.nio.channels.Selector#wakeup wakeup} method were invoked.
     *
     * <p> If none of the previous conditions hold then this thread's interrupt
     * status will be set. </p>
     *
     * <p> Interrupting a thread that is not alive need not have any effect.
     *
     * @throws  SecurityException
     *          if the current thread cannot modify this thread
     *
     * @revised 6.0
     * @spec JSR-51
     */
    public void interrupt(a) {
        // Check if it is a self call
        if (this! = Thread.currentThread())// Check security permissions, which may cause {@link * SecurityException} to be thrown.
            checkAccess();
        
        // Synchronize code blocks
        synchronized (blockerLock) {
            Interruptible b = blocker;
            // Check if it is a blocked thread call
            if(b ! =null) {
                // Set the thread interrupt flag bit
                interrupt0(); 
                // An exception is thrown, and the interrupt flag bit is set to false. In this case, we normally catch the exception and reset the interrupt flag bit
                b.interrupt(this);
                return; }}// If there is no accident, then normal set interrupt flag
        interrupt0();
    }
Copy the code
  • The thread interrupt method does not cause the thread to exit immediately. Instead, it sends a notification to the target thread telling it that someone wants you to exit
  • Can only be called by itself, otherwise it may be thrownSecurityException
  • Calling the interrupt method is up to the target thread itself to decide whether to interrupt, and if both are calledwait.join.sleep, causes the current thread to enter a blocking state, which may occurInterruptedExceptionabnormal
  • It is not reasonable for a blocked thread to call the interrupt method
  • Interrupting an inactive thread has no effect

Check if the thread is interrupted:

    /** * Tests whether this thread has been interrupted. The <i>interrupted * status</i> of the thread is unaffected by this method. Tests whether this thread has been interrupted. The thread's < I > interrupt * state </ I > is not affected by this method. * * <p>A thread interruption ignored because a thread was not alive * at the time of the interrupt will be reflected by this method * returning false. * *@return  <code>true</code> if this thread has been interrupted;
     *          <code>false</code> otherwise.
     * @see     #interrupted()
     * @revised6.0 * /
    public boolean isInterrupted(a) {
        return isInterrupted(false);
    }
Copy the code

Static method that clears the interrupt flag of the current thread:

   /** * Tests whether the current thread has been interrupted. , this method clears the thread's * < I > interrupted state </ I >. In other words, if this method is called twice in a row, the * second call will return false (unless the current thread is interrupted again, After the first call has cleared the broken * state and before the second call has checked), It) * * <p>A thread interruption ignored because A thread was not alive * at the time of the interrupt will be reflected by this method * returning false. * *@return  <code>true</code> if the current thread has been interrupted;
     *          <code>false</code> otherwise.
     * @see #isInterrupted()
     * @revised6.0 * /
    public static boolean interrupted(a) {
        return currentThread().isInterrupted(true);
    }

Copy the code

conclusion

Record my reading Thread class source code of some thinking, but for many of the local methods used can only be discouraged, there are some code do not understand, for the moment so, if there is insufficient, please leave a message to inform me, thank you! More summary notes will be made about Thread in practice.

The last

Due to the long space, record these for the moment, the follow-up will update the original article from time to time, welcome to pay attention to the public number “Zhang Shaolin students”!