Java Thread Source Parsing

Posted by craigbabe on Mon, 01 Jul 2019 01:52:13 +0200

Thread Source Parsing

Thread method is mostly used by Native, which does not allow application layer modification. It is the most basic unit of CPU scheduling. Thread resource overhead is relatively small relative to process overhead, so we generally create thread execution, not process execution.

Thread Construction Method

/**
 * Initializes a Thread.
 *
 * @param g the Thread group
 * @param target the object whose run() method gets called
 * @param name the name of the new Thread
 * @param stackSize the desired stack size for the new thread, or
 *        zero to indicate that this parameter is to be ignored.
 */
private void init(ThreadGroup g, Runnable target, String name, long stackSize) {
    Thread parent = currentThread();
    if (g == null) {
        g = parent.getThreadGroup();
    }

    g.addUnstarted();
    this.group = g;

    this.target = target;
    this.priority = parent.getPriority();
    this.daemon = parent.isDaemon();
    setName(name);

    init2(parent);

    /* Stash the specified stack size in case the VM cares */
    this.stackSize = stackSize;
    tid = nextThreadID();
}

/**
 * Throws CloneNotSupportedException as a Thread can not be meaningfully
 * cloned. Construct a new Thread instead.
 *
 * @throws  CloneNotSupportedException
 *          always
 */
@Override
protected Object clone() throws CloneNotSupportedException {
    throw new CloneNotSupportedException();
}
public Thread() {
    init(null, null, "Thread-" + nextThreadNum(), 0);
}

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


public Thread(ThreadGroup group, Runnable target) {
    init(group, target, "Thread-" + nextThreadNum(), 0);
}


public Thread(String name) {
    init(null, null, name, 0);
}

public Thread(ThreadGroup group, String name) {
    init(group, null, name, 0);
}


/** @hide */
// Android added : Private constructor - used by the runtime.
Thread(ThreadGroup group, String name, int priority, boolean daemon) {
    this.group = group;
    this.group.addUnstarted();
    // Must be tolerant of threads without a name.
    if (name == null) {
        name = "Thread-" + nextThreadNum();
    }

    // NOTE: Resist the temptation to call setName() here. This constructor is only called
    // by the runtime to construct peers for threads that have attached via JNI and it's
    // undesirable to clobber their natively set name.
    this.name = name;

    this.priority = priority;
    this.daemon = daemon;
    init2(currentThread());
    tid = nextThreadID();
}

private void init2(Thread parent) {
    this.contextClassLoader = parent.getContextClassLoader();
    this.inheritedAccessControlContext = AccessController.getContext();
    if (parent.inheritableThreadLocals != null) {
        this.inheritableThreadLocals = ThreadLocal.createInheritedMap(
                parent.inheritableThreadLocals);
    }
}


public Thread(Runnable target, String name) {
    init(null, target, name, 0);
}


public Thread(ThreadGroup group, Runnable target, String name) {
    init(group, target, name, 0);
}

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

There are many constructions in Thread. If there is no input thread name in the constructor, the Thread class will default to specify the thread name for us, that is, calling Thread- nextThreadNum(), and numbering the thread. This method is synchronous, which ensures that no asynchronous operation is performed and avoids the occurrence of the same line ID. The init() method is executed in all constructors, which is private and determines whether ThreadGroup is empty.

Thread implements the Runnable interface. How should the run method be implemented?

@Override
public void run() {
    if (target != null) {
        target.run();
    }
}

The target variable in the run method is the variable we passed in at the time of initialization. If the subclass overrides the run method, it will not call target.run().

Important methods in Thread:

start() method

/**
 * Causes this thread to begin execution; the Java Virtual Machine
 * calls the <code>run</code> method of this thread.
 * <p>
 * The result is that two threads are running concurrently: the
 * current thread (which returns from the call to the
 * <code>start</code> method) and the other thread (which executes its
 * <code>run</code> method).
 * <p>
 * It is never legal to start a thread more than once.
 * In particular, a thread may not be restarted once it has completed
 * execution.
 *
 * @exception  IllegalThreadStateException  if the thread was already
 *               started.
 * @see        #run()
 * @see        #stop()
 */
public synchronized void start() {
    /**
     * This method is not invoked for the main method thread or "system"
     * group threads created/set up by the VM. Any new functionality added
     * to this method in the future may have to also be added to the VM.
     *
     * A zero status value corresponds to state "NEW".
     */
    if (threadStatus != 0)
        throw new IllegalThreadStateException();

    /* Notify the group that this thread is about to be started
     * so that it can be added to the group's list of threads
     * and the group's unstarted count can be decremented. */
    group.add(this);

    started = false;
    try {
        nativeCreate(this, stackSize, daemon);
        started = true;
    } finally {
        try {
            if (!started) {
                group.threadStartFailed(this);
            }
        } catch (Throwable ignore) {
            /* do nothing. If start0 threw a Throwable then
              it will be passed up the call stack */
        }
    }
}

The start() method is synchronous and starts the thread for execution. The Java virtual machine will call the run method of the thread. As a result, two threads are executing, one of which is the thread that calls the start() method and the other is the thread that executes the run method. In the start() method, the first thread state judgment is that if it is a JVM newly started thread, the state of threadStatus is 0. If the thread is not 0, the exception will be reported, and then the thread will be added to the group. The result of execution in the group.add(this) method is to inform the group that the thread is going to execute, so it can be added to the group and then called. Native Create (this, stackSize, daemon) is used locally.

sleep() method

/**
 * Causes the currently executing thread to sleep (temporarily cease
 * execution) for the specified number of milliseconds plus the specified
 * number of nanoseconds, 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
 *
 * @param  nanos
 *         {@code 0-999999} additional nanoseconds to sleep
 *
 * @throws  IllegalArgumentException
 *          if the value of {@code millis} is negative, or the value of
 *          {@code nanos} is not in the range {@code 0-999999}
 *
 * @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 void sleep(long millis, int nanos)
throws InterruptedException {
    if (millis < 0) {
        throw new IllegalArgumentException("millis < 0: " + millis);
    }
    if (nanos < 0) {
        throw new IllegalArgumentException("nanos < 0: " + nanos);
    }
    if (nanos > 999999) {
        throw new IllegalArgumentException("nanos > 999999: " + nanos);
    }

    // The JLS 3rd edition, section 17.9 says: "...sleep for zero
    // time...need not have observable effects."
    if (millis == 0 && nanos == 0) {
        // ...but we still have to handle being interrupted.
        if (Thread.interrupted()) {
          throw new InterruptedException();
        }
        return;
    }

    long start = System.nanoTime();
    long duration = (millis * NANOS_PER_MILLI) + nanos;

    Object lock = currentThread().lock;

    // Wait may return early, so loop until sleep duration passes.
    synchronized (lock) {
        while (true) {
            sleep(lock, millis, nanos);

            long now = System.nanoTime();
            long elapsed = now - start;

            if (elapsed >= duration) {
                break;
            }

            duration -= elapsed;
            start = now;
            millis = duration / NANOS_PER_MILLI;
            nanos = (int) (duration % NANOS_PER_MILLI);
        }
    }
}

The sleep () method uses more threads. The purpose of this method is to make the current thread dormant for a certain period of time, but during this period the held lock is not released. In this method, the first step is to determine the dormancy time, and then to call the local method.

join() method

/**
 * Waits at most {@code millis} milliseconds for this thread to
 * die. A timeout of {@code 0} means to wait forever.
 *
 * <p> This implementation uses a loop of {@code this.wait} calls
 * conditioned on {@code this.isAlive}. As a thread terminates the
 * {@code this.notifyAll} method is invoked. It is recommended that
 * applications not use {@code wait}, {@code notify}, or
 * {@code notifyAll} on {@code Thread} instances.
 *
 * @param  millis
 *         the time to wait 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 final void join(long millis) throws InterruptedException {
    synchronized(lock) {
    long base = System.currentTimeMillis();
    long now = 0;

    if (millis < 0) {
        throw new IllegalArgumentException("timeout value is negative");
    }

    if (millis == 0) {
        while (isAlive()) {
            lock.wait(0);
        }
    } else {
        while (isAlive()) {
            long delay = millis - now;
            if (delay <= 0) {
                break;
            }
            lock.wait(delay);
            now = System.currentTimeMillis() - base;
        }
    }
    }
}

The join method is to wait for the thread to execute until the timeout or termination. It can be used as a way of thread communication. A thread calls the join (blocking) of B thread and waits for B to complete before executing further.

interrupt() method

public void interrupt() {
    if (this != Thread.currentThread())
        checkAccess();

    synchronized (blockerLock) {
        Interruptible b = blocker;
        if (b != null) {
            nativeInterrupt();
            b.interrupt(this);
            return;
        }
    }
    nativeInterrupt();
}

The interrupt() method interrupts the current thread. Generally speaking, blocking functions, such as Thread.sleep, Thread.join, Object.wait, throw an InteruptedExeption while checking the interrupt state of the thread, and clear the interrupt state of the thread.

Thread state

/**
 * A thread state.  A thread can be in one of the following states:
 * <ul>
 * <li>{@link #NEW}<br>
 *     A thread that has not yet started is in this state.
 *     </li>
 * <li>{@link #RUNNABLE}<br>
 *     A thread executing in the Java virtual machine is in this state.
 *     </li>
 * <li>{@link #BLOCKED}<br>
 *     A thread that is blocked waiting for a monitor lock
 *     is in this state.
 *     </li>
 * <li>{@link #WAITING}<br>
 *     A thread that is waiting indefinitely for another thread to
 *     perform a particular action is in this state.
 *     </li>
 * <li>{@link #TIMED_WAITING}<br>
 *     A thread that is waiting for another thread to perform an action
 *     for up to a specified waiting time is in this state.
 *     </li>
 * <li>{@link #TERMINATED}<br>
 *     A thread that has exited is in this state.
 *     </li>
 * </ul>
 *
 * <p>
 * A thread can be in only one state at a given point in time.
 * These states are virtual machine states which do not reflect
 * any operating system thread states.
 *
 * @since   1.5
 * @see #getState
 */
public enum State {
    /**
     * Thread state for a thread which has not yet started.
     */
    NEW,

    /**
     * Thread state for a runnable thread.  A thread in the runnable
     * state is executing in the Java virtual machine but it may
     * be waiting for other resources from the operating system
     * such as processor.
     */
    RUNNABLE,

    /**
     * Thread state for a thread blocked waiting for a monitor lock.
     * A thread in the blocked state is waiting for a monitor lock
     * to enter a synchronized block/method or
     * reenter a synchronized block/method after calling
     * {@link Object#wait() Object.wait}.
     */
    BLOCKED,

    /**
     * Thread state for a waiting thread.
     * A thread is in the waiting state due to calling one of the
     * following methods:
     * <ul>
     *   <li>{@link Object#wait() Object.wait} with no timeout</li>
     *   <li>{@link #join() Thread.join} with no timeout</li>
     *   <li>{@link LockSupport#park() LockSupport.park}</li>
     * </ul>
     *
     * <p>A thread in the waiting state is waiting for another thread to
     * perform a particular action.
     *
     * For example, a thread that has called <tt>Object.wait()</tt>
     * on an object is waiting for another thread to call
     * <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on
     * that object. A thread that has called <tt>Thread.join()</tt>
     * is waiting for a specified thread to terminate.
     */
    WAITING,

    /**
     * Thread state for a waiting thread with a specified waiting time.
     * A thread is in the timed waiting state due to calling one of
     * the following methods with a specified positive waiting time:
     * <ul>
     *   <li>{@link #sleep Thread.sleep}</li>
     *   <li>{@link Object#wait(long) Object.wait} with timeout</li>
     *   <li>{@link #join(long) Thread.join} with timeout</li>
     *   <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
     *   <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
     * </ul>
     */
    TIMED_WAITING,

    /**
     * Thread state for a terminated thread.
     * The thread has completed execution.
     */
    TERMINATED;
}

1,NEW

The start() method has not yet been invoked for the newly created thread

2, RUNNABLE
It can run, and it needs to wait until other resources (such as CPU) are ready to run.
3, BLOCKED
The thread calls wait () and waits for the built-in lock to enter the synchronization method or block

4,WAITING
In calling wait(),Thread.join() without parameters

5,TIMED_WAITING
Call Thread.sleep(), wait() with a time parameter, and Thread.join() with a time parameter.
6,TERMINATED
Executed thread status

Topics: Java Android jvm