premise
Recently a little lazy, nothing compares depth output. Just want to re-read at the source JUC thread pool to achieve, before the first in-depth look at Java's thread implementation, including the life cycle of the thread, and the thread context switching state switch and so on. Time of this writing, JDK version is 11.
Implementation of the Java threads
In after JDK1.2 , the Java threading model has been identified to achieve the operating system native threading model. Therefore, the current or future JDK version, operating system support how kind of threading model, to a large extent determines how the Java virtual machine thread maps, this is no way to reach an agreement, the virtual machine specification on different platforms nor qualified Java thread needs which threading model to use to achieve. Threading model affects only the size and operating costs of concurrent threads for Java programs, these differences are transparent.
Correspondence Oracle Sun JDK
or Oracle Sun JVM
in terms of its Windows version and Linux versions are using one thread model implementation (shown below).
That is a Java thread maps to a single LWP ( Light Weight Process ), whereas a lightweight thread in turn mapped to a kernel thread ( Kernel-Level the Thread ). We usually say the thread, often refers to the lightweight processes (or that we usually new java.lang.Thread
is the lightweight process instance). Front projection this thread mapping relationship may know, we have created or operated in an application java.lang.Thread
example will eventually be mapped to kernel threads in the system, if we maliciously or experimental unlimited creation java.lang.Thread
instance, will ultimately affect the normal operation of the system and even cause system crashes (you can do experiments in the Windows development environment, be sure to use an infinite loop to create and run memory sufficiently java.lang.Thread
instance).
Thread scheduling mode includes two, cooperative thread scheduling and preemptive thread scheduling.
Thread scheduling | description | Disadvantaged | Advantage |
---|---|---|---|
Collaborative thread scheduling | Thread execution time is controlled by the thread itself, actively notify the OS switching to another thread after the implementation of | If a thread to keep the CPU execution time may cause the entire system to crash | Simple, no thread synchronization problems |
Preemptive thread scheduling | Each thread is allocated by the operating system execution time, thread switching thread itself decide not help | To achieve a relatively complex operating system needs to control thread switching and synchronization | It will not be a thread blocks cause a system crash |
Java threads will eventually be mapped to the system kernel native threads, so Java thread scheduling system ultimately depends on the operating system, and the current mainstream operating system kernel thread scheduling are basically using preemptive thread scheduling. That is what can rote: the Java thread is the use of preemptive thread scheduling mode for thread scheduling .
Many operating systems provide a thread priority concept, but due to problems characteristic of the platform, the Java thread priorities and different platform system thread priorities do not match, so Java thread priorities can only be understood as " recommended priority " , it is popular java.lang.Thread#setPriority(int newPriority)
does not necessarily take effect, it is possible Java thread's priority will be to change the system itself .
Java threads state switch
The state of Java threads from java.lang.Thread
inside enumeration class java.lang.Thread$State
that:
public enum State {
NEW,
RUNNABLE,
BLOCKED,
WAITING,
TIMED_WAITING,
TERMINATED;
}
复制代码
These states described in FIG summarized as follows:
Relationship between the state of the thread switching is as follows:
By following a few simple API notes and code examples to analyze the meaning and status of the state of Java threads to switch.
NEW state
API Notes :
/**
* Thread state for a thread which has not yet started.
*
*/
NEW,
复制代码
Thread instance has not been started when the thread state.
A newly created but not yet started (not yet calling Thread#start()
method) is an example of Java threads out of NEW
state.
public class ThreadState {
public static void main(String[] args) throws Exception {
Thread thread = new Thread();
System.out.println(thread.getState());
}
}
// 输出结果
NEW
复制代码
RUNNABLE state
API Notes :
/**
* 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,
复制代码
State of the thread under the thread can be running. Runnable threads in the implementation of the Java virtual machine, but it may perform other resources to wait for the operating system, such as the processor.
When Java thread instance calls Thread#start()
later, it will enter the RUNNABLE
state. RUNNABLE
The state may be considered include two sub-states: READY
and RUNNING
.
READY
: The thread scheduling status may be changed to make it more thread schedulerRUNNING
state.RUNNING
: This state indicates that the thread is running, thread objectrun()
instruction code method is being performed corresponding CPU.
When Java thread instance Thread#yield()
method is called thread scheduler or because of scheduling, the state is likely a thread instance RUNNING
into READY
, but the thread state Thread#getState()
acquired status remains RUNNABLE
. E.g:
public class ThreadState1 {
public static void main(String[] args) throws Exception {
Thread thread = new Thread(()-> {
while (true){
Thread.yield();
}
});
thread.start();
Thread.sleep(2000);
System.out.println(thread.getState());
}
}
// 输出结果
RUNNABLE
复制代码
WAITING state
API Notes :
/**
* 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 {@code Object.wait()}
* on an object is waiting for another thread to call
* {@code Object.notify()} or {@code Object.notifyAll()} on
* that object. A thread that has called {@code Thread.join()}
* is waiting for a specified thread to terminate.
*/
WAITING,
复制代码
Wait state thread. A thread into a wait state is due to call one of the following methods:
Without timeout Object # wait ()
Without timeout Thread # join ()
LockSupport.park()
A thread in a wait state is always some special treatment in wait for another thread.
For example: a thread calls the Object # wait (), then it is waiting for Object # notify on another thread calls the object () or Object # notifyAll (); a thread calls Thread # join (), then it is waiting for another a thread end.
WAITING
Is indefinite wait state , the thread in this state will not be assigned CPU execution time. When a thread executes certain methods will enter a waiting state indefinitely until explicitly awakened, after being awakened by a thread state WAITING
more turns RUNNABLE
and then continue.
RUNNABLE Convert WAITING process (wait indefinitely) |
WAITING Converted RUNNABLE method (wake-up) |
---|---|
Object#wait() |
Object#notify() | Object#notifyAll() |
Thread#join() |
- |
LockSupport.part() |
LockSupport.unpart(thread) |
Wherein the Thread#join()
method is relatively specific, it will block a thread until the thread Examples Example finished, its source can be observed as follows:
public final void join() throws InterruptedException {
join(0);
}
public final synchronized void join(long millis)throws InterruptedException {
long base = System.currentTimeMillis();
long now = 0;
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (millis == 0) {
while (isAlive()) {
wait(0);
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
复制代码
Visible Thread#join()
is always called when the thread instance survival Object#wait()
method, which is to be completed in the thread execution isAlive()
for the time false (meaning the thread life cycle has ended) is only unblocked.
Based on WAITING
the state of an example:
public class ThreadState3 {
public static void main(String[] args) throws Exception {
Thread thread = new Thread(()-> {
LockSupport.park();
while (true){
Thread.yield();
}
});
thread.start();
Thread.sleep(50);
System.out.println(thread.getState());
LockSupport.unpark(thread);
Thread.sleep(50);
System.out.println(thread.getState());
}
}
// 输出结果
WAITING
RUNNABLE
复制代码
TIMED WAITING state
API Notes :
/**
* 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,
复制代码
It defines the state of the specific waiting time waiting in the thread. A thread enters this state is due to a specific time-out period specified call one of the following methods:
Thread.sleep()
With a timeout Object # wait ()
With a timeout Thread # join ()
LockSupport.parkNanos()
LockSupport.parkUntil ()
TIMED WAITING
Is there a deadline for wait states , and it WAITING
is somewhat similar thread in this state will not be assigned CPU execution time, but the thread in this state does not need to be explicitly awakened, just waiting for the timeout period will be awakened to reach VM , somewhat similar to alarm a fact of life.
RUNNABLE Converted TIMED WAITING method (there are waiting period) |
TIMED WAITING Convert RUNNABLE process (timeout wait release) |
---|---|
Object#wait(timeout) |
- |
Thread#sleep(timeout) |
- |
Thread#join(timeout) |
- |
LockSupport.parkNanos(timeout) |
- |
LockSupport.parkUntil(timeout) |
- |
for example:
public class ThreadState4 {
public static void main(String[] args) throws Exception {
Thread thread = new Thread(()-> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
//ignore
}
});
thread.start();
Thread.sleep(50);
System.out.println(thread.getState());
Thread.sleep(1000);
System.out.println(thread.getState());
}
}
// 输出结果
TIMED_WAITING
TERMINATED
复制代码
BLOCKED state
API Notes :
/**
* 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,
复制代码
This status indicates that a thread is blocked waiting to acquire a monitor lock. The method of synchronization blocks or synchronization code is then re-entry if the thread is blocked, the thread waiting to enter the monitor described lock synchronization or synchronization code block or method call Object # wait ().
BLOCKED
The state is blocked, the thread in this state will not be assigned CPU execution time. Thread state BLOCKED
when there are two possible scenarios:
A thread in the blocked state is waiting for a monitor lock to enter a synchronized block/method
- The thread is waiting for a monitor lock, only after obtaining the monitor lock to enter
synchronized
a code block orsynchronized
method, in this process of waiting to acquire the lock thread is blocked.
reenter a synchronized block/method after calling Object#wait()
- X thread into
synchronized
blocks of code, orsynchronized
after the method call (in this case the monitor lock has been released)Object#wait()
by blocking After the method, when receiving a call the other thread lock object TObject#notify()/notifyAll()
, but the thread T has not exit it in thesynchronized
block orsynchronized
method, the thread X still in the blocked state (API note in comments the Reenter , understand it will suddenly see the light scene 2).
A more detailed description can refer to the author previously wrote an article: in-depth understanding of Object provided and wake-up blocking API .
For the above scenario for a simple example:
public class ThreadState6 {
private static final Object MONITOR = new Object();
public static void main(String[] args) throws Exception {
Thread thread1 = new Thread(()-> {
synchronized (MONITOR){
try {
Thread.sleep(Integer.MAX_VALUE);
} catch (InterruptedException e) {
//ignore
}
}
});
Thread thread2 = new Thread(()-> {
synchronized (MONITOR){
System.out.println("thread2 got monitor lock...");
}
});
thread1.start();
Thread.sleep(50);
thread2.start();
Thread.sleep(50);
System.out.println(thread2.getState());
}
}
// 输出结果
BLOCKED
复制代码
For scenario 2 above for a simple example:
public class ThreadState7 {
private static final Object MONITOR = new Object();
private static final DateTimeFormatter F = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
public static void main(String[] args) throws Exception {
System.out.println(String.format("[%s]-begin...", F.format(LocalDateTime.now())));
Thread thread1 = new Thread(() -> {
synchronized (MONITOR) {
System.out.println(String.format("[%s]-thread1 got monitor lock...", F.format(LocalDateTime.now())));
try {
Thread.sleep(1000);
MONITOR.wait();
} catch (InterruptedException e) {
//ignore
}
System.out.println(String.format("[%s]-thread1 exit waiting...", F.format(LocalDateTime.now())));
}
});
Thread thread2 = new Thread(() -> {
synchronized (MONITOR) {
System.out.println(String.format("[%s]-thread2 got monitor lock...", F.format(LocalDateTime.now())));
try {
MONITOR.notify();
Thread.sleep(2000);
} catch (InterruptedException e) {
//ignore
}
System.out.println(String.format("[%s]-thread2 releases monitor lock...", F.format(LocalDateTime.now())));
}
});
thread1.start();
thread2.start();
// 这里故意让主线程sleep 1500毫秒从而让thread2调用了Object#notify()并且尚未退出同步代码块,确保thread1调用了Object#wait()
Thread.sleep(1500);
System.out.println(thread1.getState());
System.out.println(String.format("[%s]-end...", F.format(LocalDateTime.now())));
}
}
// 某个时刻的输出如下:
[2019-06-20 00:30:22]-begin...
[2019-06-20 00:30:22]-thread1 got monitor lock...
[2019-06-20 00:30:23]-thread2 got monitor lock...
BLOCKED
[2019-06-20 00:30:23]-end...
[2019-06-20 00:30:25]-thread2 releases monitor lock...
[2019-06-20 00:30:25]-thread1 exit waiting...
复制代码
Scene 2:
- Thread 2 calls
Object#notify()
after sleep 2000 milliseconds, and then exit the synchronized block to release the monitor lock. - Thread a sleep call 1,000 milliseconds
Object#wait()
, this time it has released the lock monitor, the thread 2 sync blocks successfully entered, the thread 1 is described in the API annotationreenter a synchronized block/method
state. - The main thread sleep 1500 milliseconds can just hit the thread 1 in the
reenter
state and its print thread state, just thatBLOCKED
state.
These three looks a bit around, read it several times more than think about should be able to understand.
TERMINATED state
API Notes :
/**
* Thread state for a terminated thread.
* The thread has completed execution.
*/
TERMINATED;
复制代码
The end of the thread corresponding to the thread state where the thread has finished.
TERMINATED
State indicates that the thread is over. A thread instance can only be started once, precisely, will only be called once Thread#run()
method, Thread#run()
after the method of execution, the thread will be more changes to the state TERMINATED
, meaning the thread life cycle has ended.
Here is a simple example:
public class ThreadState8 {
public static void main(String[] args) throws Exception {
Thread thread = new Thread(() -> {
});
thread.start();
Thread.sleep(50);
System.out.println(thread.getState());
}
}
// 输出结果
TERMINATED
复制代码
Context switching
Multithreaded environment, when the state of a thread RUNNABLE
into a non RUNNABLE
( BLOCKED
, WAITING
or TIMED_WAITING
), the respective thread context information (that is often said Context
, including the contents of CPU registers and the program counter at the point in time, etc.) need is saved to the thread later restored to RUNNABLE
be able to continue on the basis of progress in the implementation of the previous state. The state of a thread by a non- RUNNABLE
state entry RUNNABLE
may relate to a previously saved state to restore the thread context information and proceed on this basis. Here the process thread context information to save and restore is called a context switch ( Context Switch
).
Thread context switch will bring additional performance overhead, which includes saving and restoring thread context information overhead thread scheduling CPU time overhead and CPU cache content codes fail overhead (threads execute its access from the CPU cache variable than the value required from the main memory (RAM) in response to the value of the variable to be accessed faster, but the thread associated thread context switch can cause the accessed content invalidation CPU cache, the CPU generally L1 Cache
andL2 Cache
, so that the associated thread is slightly after being forced to reschedule its visit the main variables in memory to run again in order to re-create the CPU cache content).
In the Linux system, you can vmstat
view the global context switching command, for example:
$ vmstat 1
复制代码
For running Java programs, can also in the Linux system perf
to monitor command, for example:
$ perf stat -e cpu-clock,task-clock,cs,cache-reference,cache-misses java YourJavaClass
复制代码
Reference is mentioned under Windows system can bring their own tools perfmon
to monitor (in fact, is the Task Manager) thread context switching, in fact, I did not find the task manager there is no way to switch the viewing context, after searching through discovery a tool: Process Explorer . Run Process Explorer
run a Java program and see its status:
Because playing a breakpoint, you can see the context switching programs running in a total of more than 7,000, the context of the current one-second increments switch 26 (because the author set Process Explorer
to refresh the data once per second).
Monitoring thread status
If the project is running in a production environment, it is impossible to call frequently Thread#getState()
change the method to monitor the state of the thread. JDK itself provides a number of tools to monitor the state of the thread, there are some open source tools such as lightweight Ali Arthas , briefly outline JDK
some of the tools comes.
Use jvisualvm
jvisualvm
JDK comes with a heap of threads waiting JVM metrics monitoring tools, suitable for use in development and test environments. It is located JAVA_HOME/bin
under the directory.
Which 线程Dump
is similar to the buttons mentioned below jstack
command, used to derive the stack information for all threads.
Use jstack
jstack
JDK comes with a command-line tool that is used to obtain the specified function PID
of the Java process thread stack information. For example, a locally running IDEA
instances PID
is 11376, you only need to enter:
jstack 11376
复制代码
In addition, if you want to locate a specific Java process PID
, you can use the jps
command.
Use JMC
JMC
That is Java Mission Control
, it also comes with the JDK task monitoring tool that provides functionality than the jvisualvm
powerful, including MBean processing thread stack state has been viewed, the flight recorder and so on.
summary
Switching to understand Java thread state and some control measures, more conducive to the development of multi-threaded programs daily, a problem for the production environment, can quickly locate the problem through the stack information monitor thread root cause (Generally speaking, the more mainstream MVC
applications It is a request by a single thread processing, when the request occurs blocked, deriving a corresponding processing request to the blocking threads may be positioned substantially precise position, if for example the message queue RabbitMQ
, the consumer thread jam similar idea may also be utilized solve).
References:
- Jdk11 relevant source code
- "Java multi-threaded programming practical guide"
- "In-depth understanding of the Java Virtual Machine -2nd"
link
- Github Page:www.throwable.club/2019/06/23/…
- Coding Page:throwable.coding.me/2019/06/23/…
(This article End c-7-d ea-20190623 business iteration recently a little busy)