Author: small Fu Ge blog: https://bugstack.cn Github:https://github.com/fuzhengwei/CodeGuide/wiki
Precipitation, share, grow, let yourself and others can gain something! 😄
One, foreword
Test not commonly used, test you will not test, test you ignore, is the test!
Most of the tests are basically useless. Let’s not say 😄 as an exception as you do program development, especially in RPC+MQ+ sub-library sub-table, in fact, it is very difficult to let you use a machine instance to write multithreading squeezed CPU performance. Many times an MQ is thrown and consumed asynchronously. If there is no competition for resources, such as library table killing, then it is really hard to get into multi-concurrent programming and the use of locks.
But!!! Where there are exceptions, such as when you need to develop a database routing middleware, there will certainly be instances where a database resource pool will be allocated on one application instance, and resources will be allocated appropriately if there is competition. Thus, such middleware development will involve the application of some more core underlying technologies.
So, sometimes it’s not useless, it’s you.
2. Interview questions
Thanks for the plane, note! I’m playing with threads, and I’m not gonna be stopped by interviews, I said!
Xie Airplane: hey, how are you? I’m Xie Airplane!
Interviewer: Ok, are you ready for the telephone interview today?
Thank plane: ready, hey hey!
Interviewer: Well, I see you have quite a few threads in your resume. I’m going to ask you a thread how does the state change between threads?
Thank plane: pull pull pull, pull pull pull!
Interviewer: HMM, not bad. So how is the yield method used?
Xie Airplane: HMM! It’s like giving up the CPU. I haven’t used it much!
Interviewer: Take some tests, verify them, and ask you next time.
3. Thread status relationship
The enumeration class java.lang.thread. State contains the following five states:
public enum State {
NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED;
}
Copy the code
These five states describe the life cycle of a thread. In fact, the definition of this state code often appears in our daily business development. For example, an activity’s submission, approval, rejection, modification, approval, running, closing, etc., are similar. Then the thread state is transferred in the following way, as shown in Figure 20-1
New
: a newly created thread is in the waiting state.Runnable
: Runnable status, not already running, the specific thread scheduling depends on each operating system. Included in RunnableReady
,Running
When the thread calls the start() method, the thread is in the Ready state, waiting for the operating system to allocate CPU time slices, and then enters the Running state. In addition, when the yield() method is called, onlyhumilityAllows the current thread to relinquish CPU, but not necessarily, depending on the operating system. If it does, the current thread will be Ready and continue competing for CPU until execution.Timed_waiting
: The thread will not be executed or scheduled by the system until the waiting time expires. The following methods can be triggered:Thread.sleep
,Object.wait
,Thread.join
,LockSupport.parkNanos
,LockSupport.parkUntil
.Wating
: Wake-able wait state in which threads are not executed or scheduled by the system. This state can be acquired by synchronized and entered by calling the wait method. Finally, notify and NotifyAll are used to wake up. The following methods can be triggered:Object.wait
,Thread.join
,LockSupport.park
.Blocked
: When a lock contention occurs, the thread that did not acquire the lock is suspended. Synchronized locks, for example, are first acquired and executed, and those not acquired enter the blocking state.Terminated
This is the Terminated state, and moving from New to Terminated is irreversible. Generally, the program flow ends normally or an exception occurs.
Refer to enumeration hereState
The English annotation of the class understands the meaning of each state code, so let’s try to manipulate thread methods to represent these states.
Iv. Thread state test
1. NEW
Thread thread = new Thread(() -> {
});
System.out.println(thread.getState());
// NEW
Copy the code
- This state is simply the state in which thread creation has not yet started.
2. RUNNABLE
Thread thread = new Thread(() -> {
});
/ / start
thread.start();
System.out.println(thread.getState());
// RUNNABLE
Copy the code
- After the created thread starts
start()
, will enter the RUNNABLE state. Instead of executing, the thread is ready to compete for CPU resources.
3. BLOCKED
Object obj = new Object();
new Thread(() -> {
synchronized (obj) {
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
Thread thread = new Thread(() -> {
synchronized (obj) {
try {
obj.wait();
} catch(InterruptedException e) { e.printStackTrace(); }}}); thread.start();while (true) {
Thread.sleep(1000);
System.out.println(thread.getState());
}
// BLOCKED
// BLOCKED
// BLOCKED
Copy the code
- This code is a little longer, mainly to allow two threads to lock contention.
- The first thread, synchronized, acquires the lock and sleeps without releasing it.
- The second thread, synchronized, cannot acquire the lock and is suspended.
- So the final output is going to be,
BLOCKED
4. WAITING
Object obj = new Object();
Thread thread = new Thread(() -> {
synchronized (obj) {
try {
obj.wait();
} catch(InterruptedException e) { e.printStackTrace(); }}}); thread.start();while (true) {
Thread.sleep(1000);
System.out.println(thread.getState());
}
// WAITING
// WAITING
// WAITING
Copy the code
- Simply in a synchronized block or modified method
wait
Method that has not been notifiedWAITING
State. - In addition
Thread.join
The source code also calls the wait method, so the thread will also enter the wait state.
5. Timed_waiting
Object obj = new Object();
Thread thread = new Thread(() -> {
synchronized (obj) {
try {
Thread.sleep(100000);
} catch(InterruptedException e) { e.printStackTrace(); }}}); thread.start();while (true) {
Thread.sleep(1000);
System.out.println(thread.getState());
}
// TIMED_WAITING
// TIMED_WAITING
// TIMED_WAITING
Copy the code
- Given the comparison above, this state is not difficult to obtain. As long as to
Thread.sleep(100000);
That’s it.
6. Terminated
Thread thread = new Thread(() -> {
});
thread.start();
System.out.println(thread.getState());
System.out.println(thread.getState());
System.out.println(thread.getState());
// RUNNABLE
// TERMINATED
// TERMINATED
Copy the code
- This one is a little bit easier, as soon as a thread runs, its life cycle is over, it enters
TERMINATED
State.
5. Use the Thread method
In general, the most commonly used method for Thread is start, but there are other methods that may not be used much in normal development, but are often used in some frameworks. So only understand their concept, but lack of some examples to refer to! Let’s do some examples to verify these methods, including yield, wait, notify, and Join.
1. yield
Yield yields the CPU, but not necessarily, always! . This may be used in concurrent threads to ensure execution of important threads by priority, or in other special business scenarios (for example, the thread content is time-consuming and less important and can be put later).
To verify this approach, let’s do an example: start 50 threads, each doing 1000 summations. Ten of these threads perform CPU surrender operations. So, if the CPU is being ceded and the computation time of the 10 threads is long, the ceding operation is actually taking place.
Case code
private static volatile Map<String, AtomicInteger> count = new ConcurrentHashMap<>();
static class Y implements Runnable {
private String name;
private boolean isYield;
public Y(String name, boolean isYield) {
this.name = name;
this.isYield = isYield;
}
@Override
public void run(a) {
long l = System.currentTimeMillis();
for (int i = 0; i < 1000; i++) {
if (isYield) Thread.yield();
AtomicInteger atomicInteger = count.get(name);
if (null == atomicInteger) {
count.put(name, new AtomicInteger(1));
continue;
}
atomicInteger.addAndGet(1);
count.put(name, atomicInteger);
}
System.out.println("Thread number:" + name + "Execution time:" + (System.currentTimeMillis() - l) + "(milliseconds)" + (isYield ? "Yield the CPU -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --" : "Don't let the CPU")); }}public static void main(String[] args) {
for (int i = 0; i < 50; i++) {
if (i < 10) {
new Thread(new Y(String.valueOf(i), true)).start();
continue;
}
new Thread(new Y(String.valueOf(i), false)).start(); }}Copy the code
The test results
Thread Number:10Execution time:2(ms) Disallow CPU thread number:11Execution time:2(ms) Disallow CPU thread number:15Execution time:1(ms) Disallow CPU thread number:14Execution time:1(ms) Disallow CPU thread number:19Execution time:1(ms) Disallow CPU thread number:18Execution time:1(ms) Disallow CPU thread number:22Execution time:0(ms) Disallow CPU thread number:26Execution time:0(ms) Disallow CPU thread number:27Execution time:1(ms) Disallow CPU thread number:30Execution time:0(ms) Disallow CPU thread number:31Execution time:0(ms) Disallow CPU thread number:34Execution time:1(ms) Disallow CPU thread number:12Execution time:1(ms) Disallow CPU thread number:16Execution time:1(ms) Disallow CPU thread number:13Execution time:1(ms) Disallow CPU thread number:17Execution time:1(ms) Disallow CPU thread number:20Execution time:0(ms) Disallow CPU thread number:23Execution time:0(ms) Disallow CPU thread number:21Execution time:0(ms) Disallow CPU thread number:25Execution time:1(ms) Disallow CPU thread number:24Execution time:1(ms) Disallow CPU thread number:28Execution time:0(ms) Disallow CPU thread number:38Execution time:0(ms) Disallow CPU thread number:39Execution time:0(ms) Disallow CPU thread number:37Execution time:1(ms) Disallow CPU thread number:40Execution time:0(ms) Disallow CPU thread number:44Execution time:0(ms) Disallow CPU thread number:36Execution time:1(ms) Disallow CPU thread number:42Execution time:1(ms) Disallow CPU thread number:45Execution time:1(ms) Disallow CPU thread number:43Execution time:1(ms) Disallow CPU thread number:46Execution time:0(ms) Disallow CPU thread number:47Execution time:0(ms) Disallow CPU thread number:35Execution time:0(ms) Disallow CPU thread number:33Execution time:0(ms) Disallow CPU thread number:32Execution time:0(ms) Disallow CPU thread number:41Execution time:0(ms) Disallow CPU thread number:48Execution time:1(ms) Disallow CPU thread number:6Execution time:15(ms) Surrender CPU---------------------- Thread number:7Execution time:15(ms) Surrender CPU---------------------- Thread number:49Execution time:2(ms) Disallow CPU thread number:29Execution time:1(ms) Disallow CPU thread number:2Execution time:17(ms) Surrender CPU---------------------- Thread number:1Execution time:11(ms) Surrender CPU---------------------- Thread number:4Execution time:15(ms) Surrender CPU---------------------- Thread number:8Execution time:12(ms) Surrender CPU---------------------- Thread number:5Execution time:12(ms) Surrender CPU---------------------- Thread number:9Execution time:12(ms) Surrender CPU---------------------- Thread number:0Execution time:21(ms) Surrender CPU---------------------- Thread number:3Execution time:21(ms) Surrender the CPU----------------------Copy the code
- As can be seen from the test results, those who give up the CPU have completed the calculation in more than 10 milliseconds, indicating that our test is effective.
2. wait & notify
Wait and notify/ nofityAll are a pair of methods. If there is a wait, there is a wake up, otherwise the program is stuck. There is an in-depth source analysis of synchronized used in this section, and how it locks in the object header. If you forget, check out the “Synchronized Detoxification, Source analysis in-depth analysis!”
Next, we simulated lu Ding Ji · Lichun Yuan, and the qing Emperor drank tea, chanted poems and chatted about romantic life. When dignitaries come, they need to assign the servants to the master. There will be some waiting, wake up operations. Just to make you better remember this case, don’t think slanting. Qing Qing herd person is only busking huan field person, shout wheat.
Case code
public classBeautiful spring hospital{
public static void main(String[] args) {pimp pimp =newThe procuress (); Qing miss =newQing Herd (procuress); The guest officer guest =newGuest officer (procuress); Thread t_miss =new Thread(miss);
Thread t_guest = newThread(guest); t_miss.start(); t_guest.start(); }}classQing supposedimplements Runnable {bustard pimp;publicQing Hostess (procuress) {this. Bustard = bustard; }@Override
public void run(a) {
int i = 1;
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
if (i == 1) {
try{bustard. On duty qing shi ("Onfield"."500");
} catch(InterruptedException e) { e.printStackTrace(); }}else {
try{bustard. On duty qing shi ("Flower field guard"."800");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
i = (i + 1) % 2; }}}classThe guest officerimplements Runnable {bustard pimp;publicGuest officer (pimp) {this. Bustard = bustard; }@Override
public void run(a) {
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
try{bustard. Tea chant poems about romance (); }catch(InterruptedException e) { e.printStackTrace(); }}}}classThe procuress{
privateA String of qing =null;
private String price = null;
private booleanWorking status =true;
public synchronized void(String Price, String price)throws InterruptedException {
if(! Wait ();/ / wait for
thisQing Dynasty = Qing Dynasty;this.price = price; Working status =false;
notify();/ / wake up
}
public synchronized voidDrinking tea, reciting poems and chatting about romancethrows InterruptedException {
if(working status) wait();/ / wait for
System.out.println("Chat about romance:"+ clear supposed); System.out.println("Tea fee:" + price);
System.out.println("" + "" + "" + "" + "" + "" + "" + "" + "" + ""+ tell +"Finished" + "Ready to... ...");
System.out.println("* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *"); Working status =true;
notify();/ / wake up}}Copy the code
The test results
Chat about romance: Cangtanye tea fee:500Yen Aitanako ready to finish... . * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * chat pretty: flower field ridge tea money:800Yen Senko Hanada ready to finish... . * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * chat pretty: pale child of the field Tea money:500Yen Aitanako ready to finish... . * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *...Copy the code
- Effect Effect mainly shows the use of wait and notify.I’m sure you’ll remember this example!
3. join
Is a join a join of two threads? No!
A join is a wait for a thread, and when the thread completes its wait, it performs notify, which is found in the JVM source code.
Source: jdk8u_hotspot/blob/master/SRC/share/vm/runtime/thread. The CPP
void JavaThread::exit(bool destroy_vm, ExitType exit_type) {
// Notify waiters on thread object. This has to be done after exit() is called
// on the thread (if the thread is the last thread in a daemon ThreadGroup the
// group should have the destroyed bit set before waiters are notified).
ensure_join(this);
}
Copy the code
static void ensure_join(JavaThread* thread) {
/ / wake up
java_lang_Thread::set_thread(threadObj(), NULL);
lock.notify_all(thread);
}
Copy the code
Ok, this is it! Lock.notify_all (thread), at this point, is correct.
Case code
Thread thread = new Thread(() -> {
System.out.println("thread before");
try {
Thread.sleep(3000);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("thread after");
});
thread.start();
System.out.println("main begin!");
thread.join();
System.out.println("The main end!");
Copy the code
The test results
The main begin! Thread before thread after main end! Process finished with exit code0
Copy the code
Join () is a synchronized method that calls wait(). The purpose of this procedure is to make the thread holding the lock wait. Who holds the lock? The main thread is waited () because the main thread called threada.join (), which is equivalent to writing a block of synchronized code in the threada.join () code block. The JVM then calls Lock. notify_all(thread) after the child thread threadA completes execution; Waking the thread that holds the object lock, the main thread, continues execution.
- The main embodiment of this part of the verification is to add
thread.join()
The output is affected. If I don’t add,The main end!
Will be preferredthread after
Print it out ahead of time. - Join () is a synchronized method that calls wait() to put the thread holding the current synchronized lock into a wait state, known as the main thread. When the child thread finishes executing, the JVM calls Lock. notify_all(thread) and wakes up the main thread to continue executing.
Six, summarized
- Thread states and state transitions are also a must-ask question in interviews, but in addition to interviewing ourselves in development, it’s important to understand how thread states transition if you do use threads.Vague use, always feel worried, then you are a good programmer!
- Some of the deeper learning in threads is in calling native methods, which requires understanding the JVM level to see more deeply how c++ code implements this logic.
- When using threads, be sure to let yourself have a similar multi-core brain, * threads together, life and death by you! * This chapter is about this, a lot of knowledge is for the comprehensive content system of the whole set, for the subsequent introduction of other knowledge to lay a foundation. Thank you!
Seven, series recommendation
- BATJTMD, large factory recruitment, are recruiting what kind of Java programmers?
- Thread.start(), how does it start a Thread?
- Synchronized detoxification, analysis source depth analysis!
- How does volatile make memory visible? Is it necessarily invisible without volatile?
- Lu Ding Ji · Trinket, Beautiful Spring Courtyard, Heaven and Earth meeting, into the palace and other five scenes, with different plots to explain multithreading and locks, really fragrant!