One, foreword

Second, description,

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, as determined by the specific thread scheduling of each operating system. Runnable contains two states: Ready and Running. When a thread calls the start() method, the thread is in the Ready state, waiting for the operating system to allocate CPU time slices. After the allocation, the thread enters the Running state. In addition, when the yield() method is invoked, the current thread is allowed to yield the CPU, but the specific yield may or may not be determined by 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 until the waiting time expires. Timed_waiting: The thread will not be executed 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 a thread is 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, threads that have not acquired a lock are 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 hereStateThe 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()); // NEWCopy the code
  • This state is simply the state in which thread creation has not yet started.

2. RUNNABLE

Thread thread = new Thread(() -> { }); / / start the thread. The start (); System.out.println(thread.getState()); // RUNNABLECopy the code
  • After the created thread startsstart(), 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());
}
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.

  • The final output is 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
  • A synchronized block or modified method that calls wait and is not notified enters WAITING.

  • In addition, Thread. Join code also calls the wait method, so the Thread will 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 toThread.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 entersTERMINATEDState.

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")); }}Copy the code

The test results

Thread NUMBER: 10 Execution completion Time: 2 (ms) Deny CPU thread number: 11 Execution completion time: 2 (ms) Deny CPU thread number: 15 Execution completion time: 1 (ms) Deny CPU thread number: 14 Execution completion time: 1 (ms) Deny CPU thread number: 19 Execution completion Time: 1 (ms) CPU thread number not allowed: 18 Execution completion time: 1 (ms) CPU thread number not allowed: 22 Execution completion time: 0 (ms) CPU thread number not allowed: 26 Execution completion time: 0 (ms) CPU thread number not allowed: 27 Execution completion time: 1 (ms) CPU thread number not allowed: 22 Execution completion Time: 0 (ms) CPU thread number not allowed: 26 Execution completion time: 0 (ms) CPU thread number not allowed: 27 Execution completion time: 1 (ms) Do not allow CPU thread number: 30 Execution completion Time: 0 (ms) Do not allow CPU thread number: 31 Execution completion time: 0 (ms) Do not allow CPU thread number: 34 Execution completion time: 1 (ms) Do not allow CPU thread number: 12 Execution completion time: 1 (ms) Do not allow CPU thread number: 16 Execution completion Time: 1 (ms) Do not allow CPU thread number: 13 Execution completion time: 1 (ms) Do not allow CPU thread number: 17 Execution completion time: 1 (ms) Do not allow CPU thread number: 20 Execution completion time: 0 (ms) Do not allow CPU thread number: 23 Execution completion Time: 0 (ms) Do not allow CPU thread number: 21 Execution completion time: 0 (ms) Do not allow CPU thread number: 25 Execution completion time: 1 (ms) Do not allow CPU thread number: 24 Execution completion time: 1 (ms) Do not allow CPU thread number: 28 Execution completion Time: 0 (ms) Do not allow CPU thread number: 38 Execution completion time: 0 (ms) Do not allow CPU thread number: 39 Execution completion time: 0 (ms) Do not allow CPU thread number: 37 Execution completion time: 1 (ms) Do not allow CPU thread number: 40 Execution completion Time: 0 (ms) Do not allow CPU thread number: 44 Execution completion time: 0 (ms) Do not allow CPU thread number: 36 Execution completion time: 1 (ms) Do not allow CPU thread number: 42 Execution completion time: 1 (ms) Do not allow CPU thread number: 45 Execution completion Time: 1 (ms) Do not allow CPU thread number: 43 Execution completion time: 1 (ms) Do not allow CPU thread number: 46 Execution completion time: 0 (ms) Do not allow CPU thread number: 47 Execution completion time: 0 (ms) Do not allow CPU thread number: 35 Execution completion Time: 0 (ms) Do not allow CPU thread number: 33 Execution completion time: 0 (ms) Do not allow CPU thread number: 32 Execution completion time: 0 (ms) Do not allow CPU thread number: 41 Execution completion time: 0 (ms) Deny CPU thread number: 48 Execution completion Time: 1 (ms) Deny CPU thread number: 6 Execution completion time: 15 (ms) Surrender CPU---------------------- Thread number: 7 Execution completion time: 15 (ms) Surrender CPU---------------------- Thread number: 49 Execution completion Time: 2 (ms) Deny CPU thread number: 29 Execution completion time: 1 (ms) Deny CPU thread number: 2 Execution completion time: 17 (ms) yield the CPU -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- the thread number: 1 finishes execution time: 11 (ms) yield the CPU -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- the thread number: 4 finishes execution time: 15 (ms) yield the CPU -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- the thread number: 8 finishes execution time: 12 (ms) yield the CPU -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- the thread number: 5 finishes execution time: 12 (ms) yield the CPU -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- the thread number: 9 finishes execution time: 12 (ms) yield the CPU -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- the thread number: 0 finishes execution time: 21 (ms) yield the CPU -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- the thread number: 3 finishes execution time: 21 (ms) yield 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.

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

Tea fee: 500 yen Cangtanako ready to finish... . * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * chat pretty: flower field ridge tea money: 800 yen Flower field ridge to prepare... . * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * chat pretty: pale child of the field Tea money: 500 yen Pale child field to prepare... . * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *...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 (" main end!" );Copy the code

The test results

The main begin! Thread before thread after main end! Process finished with exit code 0Copy 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 manifestation of this validation is that adding thread.join() affects the output. If not, main end! Thread after will be printed 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 whole content system comprehensive, for the subsequent introduction of other knowledge to lay a foundation. Thank you!