Abstract: This article introduces you to understand threads, multithreading, and thread pools.
This article is shared by Huawei Cloud community “Understanding threads and thread pools”, original author: Glacier.
Thread 1.
In an operating system, a thread is a basic unit smaller than a process that can run independently. It is also the basic unit of CPU scheduling. The thread itself basically owns no system resources, only system resources that are needed at runtime, such as program counters, registers, and stacks. All threads in a process can share all resources in the process.
2. Multithreading
Multithreading can be understood as the ability to run multiple threads simultaneously to perform different tasks in the same program, and these threads can use multiple cores of the CPU to run at the same time. Multithreaded programming can maximize the utilization of CPU resources. If the processing of a thread (for example, the I/O thread) does not occupy CPU resources, you can make the current thread transfer CPU resources so that other threads can obtain CPU resources, and then perform corresponding tasks of other threads to maximize the utilization of CPU resources.
Thread implementation
In Java, there are three ways to implement threads, namely, inheriting Thread class, implementing Runnable interface and implementing Callable interface. The simple sample code is shown below.
1. Inherit the Thread code
package io.binghe.concurrent.executor.test; Public class ThreadTest extends Thread {@override public class ThreadTest extends Thread {@override Public void run() {//TODO in this thread to execute the business logic}}Copy the code
2. Code to implement Runnable interface
package io.binghe.concurrent.executor.test; /** * @author binghe * @version 1.0.0 * @description */ public class RunnableTest implements Runnable { Public void run() {Override public void run() {Override public void run() {Copy the code
3. Code to implement Callable interface
package io.binghe.concurrent.executor.test; import java.util.concurrent.Callable; /** * @author binghe * @version 1.0.0 * @description */ public class CallableTest implements Callable<String> {@override public String call() throws Exception {//TODO business logic executed in this thread return NULL; }}Copy the code
The life cycle of a thread
1. Life cycle
A thread has to go through many different states from its creation to its final demise, and these different thread states constitute different stages of the thread life cycle from beginning to end. The life cycle of a thread can be summarized in the following figure.
Of these, several important states are shown below.
-
NEW: Initial state, the thread is built, but the start() method has not been called.
-
RUNNABLE: RUNNABLE state. RUNNABLE state includes running state and ready state.
-
BLOCKED: a state in which a thread must wait for another thread to release a lock or to enter synchronized.
-
WAITING: A thread in this state is WAITING for other threads to notify or interrupt it before entering the next state.
-
TIME_WAITING: indicates the timeout waiting state. It can return by itself at a certain time.
-
TERMINATED: the current thread is TERMINATED.
2. Code examples
To better understand the life cycle of a thread, and the various states within the life cycle, we use code examples to output information about each state of a thread.
- WaitingTime
Create the WaitingTime class and call the timeUnit.seconds.sleep (long) method in the while(true) loop to verify the TIMED_WARTING status of the thread, as shown below.
package io.binghe.concurrent.executor.state; import java.util.concurrent.TimeUnit; /** * @author * @version 1.0.0 * @description */ public class WaitingTime implements Runnable{@override public void run() { while (true){ waitSecond(200); Public static final void waitSecond(long seconds){try {timeunit.seconds.sleep (seconds); } catch (InterruptedException e) { e.printStackTrace(); }}}Copy the code
- WaitingState
Create the WaitingState Class, which acquires the synchronized lock of the current Class object in a while(true) loop. That is, the synchronized lock is the same no matter how many instances the Class creates. And the thread will be in a wait state. Next, use the wait() method of the current Class object in synchronized to verify the WAITING state of the thread, as shown below.
package io.binghe.concurrent.executor.state; /** * @author binghe * @version 1.0.0 * @description */ public class WaitingState implements Runnable { @Override public void run() { while (true){ synchronized (WaitingState.class){ try { WaitingState.class.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } }Copy the code
- BlockedThread
BlockedThread validates the thread’s BLOCKED state primarily by calling the timeUnit.seconds.sleep (long) method in a while(true) loop within a synchronized block. When two BlockedThread threads are started, the first thread is in TIMED_WAITING state and the second thread is BLOCKED. The code is shown below.
package io.binghe.concurrent.executor.state; /** * @author binghe * @version 1.0.0 * @description */ public class BlockedThread implements Runnable { @Override public void run() { synchronized (BlockedThread.class){ while (true){ WaitingTime.waitSecond(100); }}}}Copy the code
- ThreadState
Start each thread and verify the status of the output of each thread, as shown below.
package io.binghe.concurrent.executor.state; /** * @author binghe * @version 1.0.0 * @description Public class ThreadState {public static void main(String[] args){new Thread(new WaitingTime(), "WaitingTimeThread").start(); new Thread(new WaitingState(), "WaitingStateThread").start(); New Thread(new BlockedThread(), "blockedThread01 ").start(); new Thread(new BlockedThread(), "BlockedThread-02").start(); }}Copy the code
Run the ThreadState class as shown below.
As you can see, no result information is printed. You can enter the “JPS” command on the command line to view the Running Java process.
c:\>jps
21584 Jps
17828 KotlinCompileDaemon
12284 Launcher
24572
28492 ThreadState
Copy the code
You can see that the process number of the ThreadSate process is 28492. Next, type “jstack 28492” to view the information about the ThreadSate process stack, as shown below.
c:\>jstack 28492
2020-02-15 00:27:08
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.202-b08 mixed mode):
"DestroyJavaVM" #16 prio=5 os_prio=0 tid=0x000000001ca05000 nid=0x1a4 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"BlockedThread-02" #15 prio=5 os_prio=0 tid=0x000000001ca04800 nid=0x6eb0 waiting for monitor entry [0x000000001da4f000]
java.lang.Thread.State: BLOCKED (on object monitor)
at io.binghe.concurrent.executor.state.BlockedThread.run(BlockedThread.java:28)
- waiting to lock <0x0000000780a7e4e8> (a java.lang.Class for io.binghe.concurrent.executor.state.BlockedThread)
at java.lang.Thread.run(Thread.java:748)
"BlockedThread-01" #14 prio=5 os_prio=0 tid=0x000000001ca01800 nid=0x6e28 waiting on condition [0x000000001d94f000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at java.lang.Thread.sleep(Thread.java:340)
at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386)
at io.binghe.concurrent.executor.state.WaitingTime.waitSecond(WaitingTime.java:36)
at io.binghe.concurrent.executor.state.BlockedThread.run(BlockedThread.java:28)
- locked <0x0000000780a7e4e8> (a java.lang.Class for io.binghe.concurrent.executor.state.BlockedThread)
at java.lang.Thread.run(Thread.java:748)
"WaitingStateThread" #13 prio=5 os_prio=0 tid=0x000000001ca06000 nid=0x6fe4 in Object.wait() [0x000000001d84f000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x0000000780a7b488> (a java.lang.Class for io.binghe.concurrent.executor.state.WaitingState)
at java.lang.Object.wait(Object.java:502)
at io.binghe.concurrent.executor.state.WaitingState.run(WaitingState.java:29)
- locked <0x0000000780a7b488> (a java.lang.Class for io.binghe.concurrent.executor.state.WaitingState)
at java.lang.Thread.run(Thread.java:748)
"WaitingTimeThread" #12 prio=5 os_prio=0 tid=0x000000001c9f8800 nid=0x3858 waiting on condition [0x000000001d74f000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at java.lang.Thread.sleep(Thread.java:340)
at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386)
at io.binghe.concurrent.executor.state.WaitingTime.waitSecond(WaitingTime.java:36)
at io.binghe.concurrent.executor.state.WaitingTime.run(WaitingTime.java:29)
at java.lang.Thread.run(Thread.java:748)
"Service Thread" #11 daemon prio=9 os_prio=0 tid=0x000000001c935000 nid=0x6864 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"C1 CompilerThread3" #10 daemon prio=9 os_prio=2 tid=0x000000001c88c800 nid=0x6a28 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"C2 CompilerThread2" #9 daemon prio=9 os_prio=2 tid=0x000000001c880000 nid=0x6498 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"C2 CompilerThread1" #8 daemon prio=9 os_prio=2 tid=0x000000001c87c000 nid=0x693c waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"C2 CompilerThread0" #7 daemon prio=9 os_prio=2 tid=0x000000001c87b800 nid=0x5d00 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"Monitor Ctrl-Break" #6 daemon prio=5 os_prio=0 tid=0x000000001c862000 nid=0x6034 runnable [0x000000001d04e000]
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
at java.net.SocketInputStream.read(SocketInputStream.java:171)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
- locked <0x0000000780b2fd88> (a java.io.InputStreamReader)
at java.io.InputStreamReader.read(InputStreamReader.java:184)
at java.io.BufferedReader.fill(BufferedReader.java:161)
at java.io.BufferedReader.readLine(BufferedReader.java:324)
- locked <0x0000000780b2fd88> (a java.io.InputStreamReader)
at java.io.BufferedReader.readLine(BufferedReader.java:389)
at com.intellij.rt.execution.application.AppMainV2$1.run(AppMainV2.java:64)
"Attach Listener" #5 daemon prio=5 os_prio=2 tid=0x000000001c788800 nid=0x6794 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"Signal Dispatcher" #4 daemon prio=9 os_prio=2 tid=0x000000001c7e3800 nid=0x3354 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"Finalizer" #3 daemon prio=8 os_prio=1 tid=0x000000001c771000 nid=0x6968 in Object.wait() [0x000000001cd4f000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x0000000780908ed0> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:144)
- locked <0x0000000780908ed0> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:165)
at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:216)
"Reference Handler" #2 daemon prio=10 os_prio=2 tid=0x000000001c770800 nid=0x6590 in Object.wait() [0x000000001cc4f000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x0000000780906bf8> (a java.lang.ref.Reference$Lock)
at java.lang.Object.wait(Object.java:502)
at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
- locked <0x0000000780906bf8> (a java.lang.ref.Reference$Lock)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)
"VM Thread" os_prio=2 tid=0x000000001a979800 nid=0x5c2c runnable
"GC task thread#0 (ParallelGC)" os_prio=0 tid=0x00000000033b9000 nid=0x4dc0 runnable
"GC task thread#1 (ParallelGC)" os_prio=0 tid=0x00000000033ba800 nid=0x6690 runnable
"GC task thread#2 (ParallelGC)" os_prio=0 tid=0x00000000033bc000 nid=0x30b0 runnable
"GC task thread#3 (ParallelGC)" os_prio=0 tid=0x00000000033be800 nid=0x6f68 runnable
"GC task thread#4 (ParallelGC)" os_prio=0 tid=0x00000000033c1000 nid=0x6478 runnable
"GC task thread#5 (ParallelGC)" os_prio=0 tid=0x00000000033c2000 nid=0x4fe4 runnable
"GC task thread#6 (ParallelGC)" os_prio=0 tid=0x00000000033c5000 nid=0x584 runnable
"GC task thread#7 (ParallelGC)" os_prio=0 tid=0x00000000033c6800 nid=0x6988 runnable
"VM Periodic Task Thread" os_prio=2 tid=0x000000001c959800 nid=0x645c waiting on condition
JNI global references: 12
Copy the code
The thread named WaitingTimeThread is in TIMED_WAITING state. The thread named WaitingStateThread is in a WAITING state. The thread named BlockedThread-01 is in TIMED_WAITING; The thread named BlockedThread-02 is BLOCKED.
Note: Using JPS and the jstack command, you can analyze the exception information of Java processes in the online production environment.
You can also directly print the stack information of the thread by clicking the diagram shown in IDEA below.
The output is basically the same as the output of the jstack process NUMBER command.
Click to follow, the first time to learn about Huawei cloud fresh technology ~