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
Runtime
Class exit methodexit
Is called and the security manager allows an exit operation- All non-daemon threads are dead, or
run
Method completes and returns results normally, orrun
Method 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:
-
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
-
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
-
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
-
Custom ThreadGroup ThreadGroup and task Runnable object constructor
public Thread(ThreadGroup group, Runnable target) { init(group, target, "Thread-" + nextThreadNum(), 0); } Copy the code
-
Constructor for custom thread name name
public Thread(String name) { init(null.null, name, 0); } Copy the code
-
Constructor for custom ThreadGroup ThreadGroup and thread name name
public Thread(ThreadGroup group, String name) { init(group, null, name, 0); } Copy the code
-
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
-
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
-
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:
- inheritance
Thread
Class, rewriterun
Method, then the execution is directrun
Method logic is not usedtarget.run();
- implementation
Runnable
Interface, overriderun
Method, becauseJava
The single-inheritance limit for thread creation is usually more flexible in this way, where the real execution logic is left to customizationRunnable
To 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 execution
synchronized
Block 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 thrown
SecurityException
- Calling the interrupt method is up to the target thread itself to decide whether to interrupt, and if both are called
wait
.join
.sleep
, causes the current thread to enter a blocking state, which may occurInterruptedException
abnormal - 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”!