Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

Summarize Thread threads, state transitions, method usage, principle analysis

2025-02-24 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article focuses on "summing up Thread threads, state transition, method use, principle analysis", interested friends may wish to take a look. The method introduced in this paper is simple, fast and practical. Next let the editor to take you to learn "summary of Thread threads, state transition, method use, principle analysis"!

I. Preface

The exam is not commonly used, you will not, the test you ignore, is the exam!

Most of the exams are not very useful. Let's not talk about the exception. Just like you do program development, especially in RPC+MQ+, it's hard to see how you can use a machine instance to write multithreaded CPU performance. Most of the time is to throw out a MQ, asynchronous consumption. If there is no resource competition, such as library table seconds, then it is really difficult for you to have access to multi-concurrent programming and the use of locks.

But! Where there are exceptions, such as if you need to develop a database routing middleware, it is certain that the database resource pool will be allocated on an application instance, and if there is competition, it is necessary to allocate resources reasonably. In this way, middleware development like this will involve the application of some more core and underlying technologies.

So, sometimes it's not useless, but you're useless.

Second, interview questions

Thank you for the plane. I'm done with the thread, and the interview can't stop me, I said!

Xie Ji: Hey, how do you do? I'm Xie Ji!

Interviewer: OK, are you ready for today's phone interview?

Thank you for the plane: ready, hey!

Interviewer: well, I see you have a lot of threaded stuff on your resume, and you seem to know it well. Let me ask you a thread, that is, how does the state transition between threads?

"Xie Ji": pull, pull, pull!

Interviewer: well, it's not bad. So how does the yield method work?

Thank you for flying: mm-hmm! It seems to be giving up CPU. I haven't used it very much!

Interviewer: do a test, verify it, and ask you next time.

III. Thread status relationship

The thread state description of Java is described in the enumeration class java.lang.Thread.State, which includes the following five states:

Public enum State {

NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED

}

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, review, reject, modify, pass, run, close, etc., are similar. Then the state of the thread is transferred through the following figure, as shown in figure 20-1

Figure 20-1 Thread State flow New: a newly created thread is in a waiting state. Runnable: runnable state, not already running, specific thread scheduling for each operating system to decide. The Runnable includes two states: Ready and Running. When the thread calls the start () method, the thread is in the ready Ready state, waiting for the operating system to allocate the CPU time slice, and then entering the Running running state after allocation. In addition, when the yield () method is called, it is only modest to allow the current thread to give up the CPU, but it is up to the operating system to decide whether or not to do so. If so, the current thread will continue to compete for CPU in the Ready state until execution. Timed_waiting: when CPU resources are released within a specified period of time, 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: a wakeable wait state in which the thread is not executed or scheduled by the system. This state can be locked through synchronized, and the wait method is called to enter the waiting state. Finally, it wakes up through notify and notifyall. The following methods can be triggered: Object.wait, Thread.join, LockSupport.park. Blocked: when lock contention occurs, the thread that does not acquire the lock is suspended. For example, synchronized locks, those that are acquired first are executed first, and those that are not acquired enter the blocking state. Terminated: this is the termination state, and the transition from New to Terminated is irreversible. Generally speaking, the program process ends normally or an exception occurs.

Here, refer to the English comments of the enumerated State class to understand the meaning of each status code, and then we will try to manipulate the thread method to reflect these states.

4. Thread status test 1. NEWThread thread = new Thread (()-> {

});

System.out.println (thread.getState ())

/ / NEW

This state is simple, that is, when the thread creation is not started. 2. RUNNABLEThread thread = new Thread (()-> {

});

/ / start

Thread.start ()

System.out.println (thread.getState ())

/ / RUNNABLE

After the created thread starts start (), it enters the RUNNABLE state. However, it is not necessarily executing at this time, but rather that the thread is ready to compete for CPU resources. 3. BLOCKEDObject 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

This code is a little longer, mainly to make the two threads compete for locks. The first thread, synchronized, hibernates after acquiring the lock without releasing the lock. The second thread, synchronized, cannot acquire the lock and is suspended. Then the final output will be BLOCKED4. WAITINGObject 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

As long as the wait method is called in the synchronized code block or decorated method, it will enter the WAITING state without being notify. In addition, the wait method is also called in the Thread.join source code, so it also puts the thread into a waiting state. 5. TIMED_WAITINGObject 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

With the comparison of the above state acquisition, it is not difficult to obtain this state. Just change it to Thread.sleep (100000); it's fine. 6. TERMINATEDThread thread = new Thread (()-> {

});

Thread.start ()

System.out.println (thread.getState ())

System.out.println (thread.getState ())

System.out.println (thread.getState ())

/ / RUNNABLE

/ / TERMINATED

/ / TERMINATED

This is relatively simple. As long as a thread finishes running and its life cycle ends, it enters the TERMINATED state. Fifth, the use of Thread method

In general, the most commonly used method in Thread is start startup, in addition to some other methods may not be used in ordinary development, but these methods often appear in some frameworks. So only understand their concepts, but lack of some examples to refer to! Next, let's do some examples to verify these methods, including: yield, wait, notify, join.

1. Yield

The yield method gives up CPU, but not necessarily, it must be. This may be used in some threads that start at the same time to ensure the execution of important threads according to priority, or in other special business scenarios (for example, the content of this thread is time-consuming and less important, and can be placed later).

To verify this method, let's do an example: start 50 threads, each doing 1000 additions and calculations. Ten of these threads perform a yield CPU operation. "then", if the calculation and summation time of the 10 threads in the CPU is relatively long, it means that the surrender operation is indeed being carried out.

"case Code"

Private static volatile Map 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 () {

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("线程编号:" + name + " 执行完成耗时:" + (System.currentTimeMillis() - l) + " (毫秒)" + (isYield ? "让出CPU----------------------" : "不让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(); } } 「测试结果」 线程编号:10 执行完成耗时:2 (毫秒)不让CPU 线程编号:11 执行完成耗时:2 (毫秒)不让CPU 线程编号:15 执行完成耗时:1 (毫秒)不让CPU 线程编号:14 执行完成耗时:1 (毫秒)不让CPU 线程编号:19 执行完成耗时:1 (毫秒)不让CPU 线程编号:18 执行完成耗时:1 (毫秒)不让CPU 线程编号:22 执行完成耗时:0 (毫秒)不让CPU 线程编号:26 执行完成耗时:0 (毫秒)不让CPU 线程编号:27 执行完成耗时:1 (毫秒)不让CPU 线程编号:30 执行完成耗时:0 (毫秒)不让CPU 线程编号:31 执行完成耗时:0 (毫秒)不让CPU 线程编号:34 执行完成耗时:1 (毫秒)不让CPU 线程编号:12 执行完成耗时:1 (毫秒)不让CPU 线程编号:16 执行完成耗时:1 (毫秒)不让CPU 线程编号:13 执行完成耗时:1 (毫秒)不让CPU 线程编号:17 执行完成耗时:1 (毫秒)不让CPU 线程编号:20 执行完成耗时:0 (毫秒)不让CPU 线程编号:23 执行完成耗时:0 (毫秒)不让CPU 线程编号:21 执行完成耗时:0 (毫秒)不让CPU 线程编号:25 执行完成耗时:1 (毫秒)不让CPU 线程编号:24 执行完成耗时:1 (毫秒)不让CPU 线程编号:28 执行完成耗时:0 (毫秒)不让CPU 线程编号:38 执行完成耗时:0 (毫秒)不让CPU 线程编号:39 执行完成耗时:0 (毫秒)不让CPU 线程编号:37 执行完成耗时:1 (毫秒)不让CPU 线程编号:40 执行完成耗时:0 (毫秒)不让CPU 线程编号:44 执行完成耗时:0 (毫秒)不让CPU 线程编号:36 执行完成耗时:1 (毫秒)不让CPU 线程编号:42 执行完成耗时:1 (毫秒)不让CPU 线程编号:45 执行完成耗时:1 (毫秒)不让CPU 线程编号:43 执行完成耗时:1 (毫秒)不让CPU 线程编号:46 执行完成耗时:0 (毫秒)不让CPU 线程编号:47 执行完成耗时:0 (毫秒)不让CPU 线程编号:35 执行完成耗时:0 (毫秒)不让CPU 线程编号:33 执行完成耗时:0 (毫秒)不让CPU 线程编号:32 执行完成耗时:0 (毫秒)不让CPU 线程编号:41 执行完成耗时:0 (毫秒)不让CPU 线程编号:48 执行完成耗时:1 (毫秒)不让CPU 线程编号:6 执行完成耗时:15 (毫秒)让出CPU---------------------- 线程编号:7 执行完成耗时:15 (毫秒)让出CPU---------------------- 线程编号:49 执行完成耗时:2 (毫秒)不让CPU 线程编号:29 执行完成耗时:1 (毫秒)不让CPU 线程编号:2 执行完成耗时:17 (毫秒)让出CPU---------------------- 线程编号:1 执行完成耗时:11 (毫秒)让出CPU---------------------- 线程编号:4 执行完成耗时:15 (毫秒)让出CPU---------------------- 线程编号:8 执行完成耗时:12 (毫秒)让出CPU---------------------- 线程编号:5 执行完成耗时:12 (毫秒)让出CPU---------------------- 线程编号:9 执行完成耗时:12 (毫秒)让出CPU---------------------- 线程编号:0 执行完成耗时:21 (毫秒)让出CPU---------------------- 线程编号:3 执行完成耗时:21 (毫秒)让出CPU---------------------- 从测试结果可以看到,那些让出 CPU 的,执行完计算已经在10毫秒以上,说明我们的测试是效果的。2. wait & notify wait 和 notify/nofityall,是一对方法,有一个等待,就会有一个叫醒,否则程序就夯在那不动了。关于这部分会使用到的 synchronized 在之前小傅哥有深入的源码分析,讲到它是怎么加锁在对象头的,如果你忘记了可以翻翻看 《synchronized 解毒,剖析源码深度分析!》 接下来我们模拟鹿鼎记·丽春院,清倌喝茶吟诗聊风月日常。当有达官贵人来时,需要分配清倌给大老爷。中间会有一些等待、叫醒操作。只为让你更好的记住这样的案例,不要想歪喽。清倌人即是只卖艺欢场人,喊麦的。 「案例代码」 public class 丽春院 { public static void main(String[] args) { 老鸨 鸨子 = new 老鸨(); 清倌 miss = new 清倌(鸨子); 客官 guest = new 客官(鸨子); Thread t_miss = new Thread(miss); Thread t_guest = new Thread(guest); t_miss.start(); t_guest.start(); } } class 清倌 implements Runnable { 老鸨 鸨子; public 清倌(老鸨 鸨子) { this.鸨子 = 鸨子; } @Override public void run() { int i = 1; while (true) { try { Thread.sleep(1000); } catch (InterruptedException e1) { e1.printStackTrace(); } if (i == 1) { try { 鸨子.在岗清倌("苍田野子", "500 日元"); } catch (InterruptedException e) { e.printStackTrace(); } } else { try { 鸨子.在岗清倌("花田岗子", "800 日元"); } catch (InterruptedException e) { e.printStackTrace(); } } i = (i + 1) % 2; } } } class 客官 implements Runnable { 老鸨 鸨子; public 客官(老鸨 鸨子) { this.鸨子 = 鸨子; } @Override public void run() { while (true) { try { Thread.sleep(1000); } catch (InterruptedException e1) { e1.printStackTrace(); } try { 鸨子.喝茶吟诗聊风月(); } catch (InterruptedException e) { e.printStackTrace(); } } } } class 老鸨 { private String 清倌 = null; private String price = null; private boolean 工作状态 = true; public synchronized void 在岗清倌(String 清倌, String price) throws InterruptedException { if (!工作状态) wait();//等待 this.清倌 = 清倌; this.price = price; 工作状态 = false; notify();//叫醒 } public synchronized void 喝茶吟诗聊风月() throws InterruptedException { if (工作状态) wait();//等待 System.out.println("聊风月:" + 清倌); System.out.println("茶水费:" + price); System.out.println(" " + " " + " " + " " + " " + " " + " " + " " + " " + " " + 清倌 + "完事" + "准备 ... ..."); System.out.println("****************************************"); 工作状态 = true; notify();//叫醒 } } 「测试结果」 聊风月:苍田野子 茶水费:500 日元 苍田野子完事准备 ... ... **************************************** 聊风月:花田岗子 茶水费:800 日元 花田岗子完事准备 ... ... **************************************** 聊风月:苍田野子 茶水费:500 日元 苍田野子完事准备 ... ... **************************************** ... 效果效果主要体现 wait、notify,这两个方法的使用。 我相信你一定能记住这个例子!3. join join 是两个线程的合并吗?不是的! join 是让线程进入 wait ,当线程执行完毕后,会在JVM源码中找到,它执行完毕后,其实执行notify,也就是 等待 和 叫醒 操作。 「源码」:jdk8u_hotspot/blob/master/src/share/vm/runtime/thread.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); } static void ensure_join(JavaThread* thread) { // 叫醒 java_lang_Thread::set_thread(threadObj(), NULL); lock.notify_all(thread); } 好的,就是这里!lock.notify_all(thread),执行到这,就对上了。 「案例代码」 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 ("main end!")

"Test results"

Main begin!

Thread before

Thread after

Main end!

Process finished with exit code 0

First of all, join () is a synchronized method that calls wait (). The purpose of this process is to get the thread holding the synchronization lock into waiting, so who holds the synchronization lock? The answer is the main thread, because the main thread calls the threadA.join () method, which is equivalent to writing a synchronous code block in the threadA.join () code. Who executes this code is the main thread, so the main thread is wait (). Then after the child thread threadA finishes executing, JVM will call lock.notify_all (thread); wake up the thread holding the threadA object lock, that is, the main thread, and continue to execute.

The main embodiment of this part of the verification is that the addition of thread.join () will affect the output. If not, main end! Priority will be given to thread after printing ahead of time. "join () is a synchronized method," in which the wait () method is called to put the thread holding the current synchronization lock into a waiting state, that is, the main thread. When the child thread finishes executing, we can see from the source code that JVM calls lock.notify_all (thread), so the main thread is awakened to continue execution. At this point, I believe that everyone on the "summary of Thread threads, state transition, method use, principle analysis," have a deeper understanding, might as well to the actual operation of it! Here is the website, more related content can enter the relevant channels to inquire, follow us, continue to learn!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report