The thread is the smallest carrier that the computation program runs, because the hardware level of single single-core CPU develops to a certain bottleneck period, so there is multi-core multi-CPU, which directly leads to the complexity of multithreaded programming of programmers. This shows the importance of threading for high-performance development.
So the thread has several states in the computer, how do they switch between them? What's the difference between sleep and wait? How do notify and Notifyall work? With these questions, let's take a look at Java threads!
The status of thread
Let's take a look at what kinds of states are in the thread class and find this enumeration in Thread.class, which defines the state of the thread:
public enum State { NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED;}
As shown in the following:
- New new state, which is created by the thread and does not have the state when the Start method is executed
- The RUNNABLE is operational and the thread is started, but waits for the appropriate resource (such as IO or time slice switchover) to start executing
- BLOCKED blocked state, when encountered synchronized or lock and did not obtain the corresponding lock, it will enter this state
- Waiting wait state, when called
Object.wait
or Thread.join()
not set time, at or LockSupport.park
, will enter the waiting state.
- Timed_waiting time waits, when called or either or or
Thread.sleep()
Object.wait(xx)
Thread.join(xx)
LockSupport.parkNanos
LockSupport.partUntil
, enters the state
- TERMINATED State of terminating state, thread interruption, or end of run
First come the difference between sleep and wait
Because the wait method is on an object, and the Sleep method is on the thread, when you call Thread.Sleep, the state of the object cannot be changed, and therefore the lock is not released.
This reminds me of my family's two masters, a teddy a beautiful short, although they are different species, but they have the same hobby, is to love to eat beef. Occasionally give them two eating, but only a food basin, each time only one master eat meat. This is like two threads, contending for the same variable. If you use Thread.Sleep, they will not release resources such as locks after they have finished eating, and will be released if you use Wait.
Look at the following code in detail:
Package Cn.xingoo.test.basic.thread;public class Animaleat {public static void main (string[] args) { SYSTEM.OUT.PRINTLN ("There are 20 pieces of meat in the basin"); Animal Animal = new Animal (); try{thread tidy = new Thread (Animal, "Teddy"); Thread cat = new Thread (animal, "US short"); Tidy.start (); Cat.start (); }catch (Exception e) {e.printstacktrace (); } System.out.println ("The meat in the pot is finished!") "); }}class Animal implements Runnable {int count = 0; @Override public void Run () {while (Count <) {synchronized (this) {try { System.out.println (Thread.CurrentThread (). GetName () + "strenuous first" +count+ "Block Meat"); count++; Thread.Sleep (100); This.wait (100); } catch (Interruptedexception e) {e.printstacktrace (); } } } }}
When using this.wait (100), the following information is output:
盆里有20块肉泰迪吃力第0块肉美短吃力第1块肉盆里的肉吃完了!泰迪吃力第2块肉美短吃力第3块肉泰迪吃力第4块肉美短吃力第5块肉泰迪吃力第6块肉美短吃力第7块肉泰迪吃力第8块肉美短吃力第9块肉泰迪吃力第10块肉美短吃力第11块肉美短吃力第12块肉泰迪吃力第13块肉美短吃力第14块肉泰迪吃力第15块肉美短吃力第16块肉泰迪吃力第17块肉美短吃力第18块肉泰迪吃力第19块肉
It can be found that the output of the information is not a perfect alternation, because after the call to wait, and not necessarily immediately when another thread executes, but according to the CPU time slicing rotation and other conditions to decide, the turn to see the luck.
When using Thread.Sleep (100), you can get the following information:
盆里有20块肉泰迪吃力第0块肉盆里的肉吃完了!泰迪吃力第1块肉泰迪吃力第2块肉泰迪吃力第3块肉泰迪吃力第4块肉泰迪吃力第5块肉泰迪吃力第6块肉泰迪吃力第7块肉泰迪吃力第8块肉泰迪吃力第9块肉泰迪吃力第10块肉泰迪吃力第11块肉泰迪吃力第12块肉泰迪吃力第13块肉泰迪吃力第14块肉泰迪吃力第15块肉泰迪吃力第16块肉泰迪吃力第17块肉泰迪吃力第18块肉美短吃力第19块肉泰迪吃力第20块肉
Notice that there is a beautiful short at the back. This is because the synchronized code is synchronized in the while loop, so the last two masters have entered the while, before they begin to wait for the corresponding lock. This led to the 19th time another master.
In summary, sleep does not release the thread's lock, and wait frees the thread's resources.
Talk more about wait with notify and Notifyall
Wait, notify, notifyall These are generally used together. However, there are several important points to note:
- When you call the Wait\notify\notifyall method, you need to use it with a lock or synchronized, or you will get an error
java.lang.IllegalMonitorStateException
, because at any moment, the control of the object can only be held by one thread, so when you call wait and so on, you must ensure control over it.
- If you call wait methods on a simple object, you will get an error if they are assigned, because the assignment is equivalent to the original object being modified, so if there is a modification requirement you can wrap the layer outside.
- Notify can wake up a thread waiting on the object, and Notifyall can wake up all the waiting threads.
- Wait (XXX) suspends the thread, frees the object's resources, and then recovers automatically when the timer ends, and wait () must be called by another thread to notify or Notifyall to wake.
To cite a popular example, I remember in high school, every morning after school, everyone is very nervous-because at that time the small restaurant just broadcast a number of Hong Kong and Taiwan drama, we are always willing to rob TV next to the location, so every time near noon school, we are ready to sprint running.
But some teachers always willing to press the hall, make everyone complain.
For example, the following teacher will sometimes use Notifyall to inform Everyone group school, and sometimes will check the endorsement, back good, to go.
Package Cn.xingoo.test.basic.thread;public class School {private Dingling dingling = new dingling (false); Class Teacher extends thread{Teacher (String name) {super (name); } @Override public void Run () {//synchronized (dingling) {try { Dingling.wait (3000); } catch (Interruptedexception e) {e.printstacktrace (); } Dingling.flag = true; System.out.println ("After School"); Dingling.notifyall (); /*for (int i = 0; i < 3; i++) {System.out.println ("Put a Walk"); Dingling.notify (); try {dingling.wait (1000); } catch (Interruptedexception e) {e.printstacktrace (); }}*//}}} class Student extends thread{Student (String naMe) {super (name); } @Override public void Run () {synchronized (dingling) {while (!dingling.flag) { System.out.println (Thread.CurrentThread (). GetName () + "start Waiting"); try {dingling.wait (); } catch (Interruptedexception e) {e.printstacktrace (); }} System.out.println (Thread.CurrentThread (). GetName () + "go to Dinner"); }}} public static void Main (string[] args) {School School = new School (); Teacher Teacher = school.new Teacher ("Teacher"); Student Zhangsan = school.new Student ("Zhang San"); Student lisi = School.new Student ("John Doe"); Student Wangwu = School.new Student ("Harry"); Teacher.start (); Zhangsan.start (); Lisi.start (); Wangwu.start (); }}class dingling{Boolean flag = false; Public dingling (Boolean flag) { This.flag = Flag; }}
When the teacher shouted after the school, that is called dingLing.notifyAll();
, will get the following output:
张三开始等待李四开始等待王五开始等待放学啦王五去吃饭啦李四去吃饭啦张三去吃饭啦
If you check the endorsement, then each teacher will only call once notify, let a classmate (thread) walk (work), you will get the following output:
张三开始等待李四开始等待王五开始等待放一个走吧张三去吃饭啦放一个走吧李四去吃饭啦放一个走吧王五去吃饭啦
Note that the call to wait can release dingling occupancy, so that other threads to check, if changed to Thread.Sleep, interested in children's shoes can go to see the effect!
Reference
- The simplest example illustrates how wait, notify, and Notifyall are used: http://longdick.iteye.com/blog/453615
- The difference between Java sleep and wait: http://www.jb51.net/article/113587.htm
- Sleep and wait doubts: https://www.zhihu.com/question/23328075
The use of sleep, wait, notify, and Notifyall in Java through two small chestnuts