Preface: Five states of threads

This article is a branch of thread thread. It is my understanding to take a look at the state of sleep and wait and some thread states. The graph on the web looks a little ugly.

1.New: New Thread ~ thread.start period 2.Runnable: execution period that can be scheduled by the CPU. The Running state is when the thread obtains THE CPU permission and executes the CPU. The Blocked state is when the thread gives up the CPU right for some reason and stops Running temporarily. | - waiting for blocking: by the calling threadwait() method to make the thread wait for a job to complete. | - synchronous blocking: thread in failed to get a synchronized synchronous lock (because the lock is occupied by other threads) | - other block: by the calling thread sleep () or the join () or the I/O request 5. Dead death status: A thread terminates its life cycle when it finishes executing or exits the run() method because of an exception.Copy the code

Thread. Sleep

The current thread is paused and Blocked, relinquishing the CPU fragment to another thread.

1. Test code:
public class Main0 {
    static SimpleDateFormat sdf = new SimpleDateFormat("mm:ss");

    public static void main(String[] args) {
        new Thread(new Car()).start();
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        new Thread(new Ambulance()).start();
    }

    private static class Car implements Runnable {
        @Override
        public void run() {
            System.out.println(sdf.format(System.currentTimeMillis()) + ": The car started and ran down the road.");
            System.out.println(sdf.format(System.currentTimeMillis()) + ": The car came to the finish line");
        }
    }

    private static class Ambulance implements Runnable {
        @Override
        public void run() {
            System.out.println(sdf.format(System.currentTimeMillis()) + ": Ambulance starts running on the road.");
            System.out.println(sdf.format(System.currentTimeMillis()) + ": Ambulance runs to the finish line"); }}}Copy the code

2. Result analysis: Note02:29 represents the minute second of the current moment, which is 2 minutes and 29 seconds

-- -- -- - > [results] -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 02:29: the car to start, run 02:29: on the road a car ran to the finish line 02:31: ambulances to start and run on the road 02:31: an ambulance ran to the finish lineCopy the code

Inline sleep and synchronized

1. The child thread is hibernated
private static class Car implements Runnable {
    @Override
    public void run() {
        System.out.println(sdf.format(System.currentTimeMillis()) + ": The car started and ran down the road.");
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(sdf.format(System.currentTimeMillis()) + ": The car came to the finish line"); }}Copy the code

2. Result analysis

The sleep of the main thread does not affect the running of the Car child thread (sleep).

18:48: The car starts and runs on the road. 18:50: the ambulance starts and runs on the road. 18:50: the ambulance runs to the endCopy the code

3. When locked in sleep

Add synchronized to thread 1 (where SDF objects are used)

public class Main2 {
    static SimpleDateFormat sdf = new SimpleDateFormat("mm:ss");
    public static void main(String[] args) {
        new Thread(new Car()).start();
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        new Thread(new Ambulance()).start();
    }

    private static class Car implements Runnable {
        @Override
        public void run() {
            synchronized (sdf){
                System.out.println(sdf.format(System.currentTimeMillis()) + ": The car started and ran down the road.");
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(sdf.format(System.currentTimeMillis()) + ": The car came to the finish line");
            }
        }
    }

    private static class Ambulance implements Runnable {
        @Override
        public void run() {
            synchronized (sdf){
                System.out.println(sdf.format(System.currentTimeMillis()) + ": Ambulance starts running on the road.");
                System.out.println(sdf.format(System.currentTimeMillis()) + ": Ambulance runs to the finish line"); }}}}Copy the code

2. Result analysis

The Car thread and the Ambulance thread use the same lock while running. The Ambulance thread does not release the lock while sleeping so it waits for the Car thread to complete before executing

23:46: The car starts, on the road to run 23:51: the car runs to the end 23:51: the ambulance starts, on the road to run 23:51: the ambulance runs to the endCopy the code

Three,Object#wait()Function of method

Calling wait() on thread T1 releases the lock held by t1, T1 is placed in A wait queue (Blocked) until another thread calls notify() or notifyAll() on object A. T1 is placed in A synchronous queue (Blocked). T1 will enter the ready state Runnable after acquiring the lock, and will continue to execute after acquiring the CPU scheduling right.


1. Use of wait

Wait () (sdf.wait()); wait() (sdf.wait()); Otherwise InterruptedException is thrown

private static class Car implements Runnable {
    @Override
    public void run() {
        synchronized (sdf) {
            System.out.println(sdf.format(System.currentTimeMillis()) + ": The car started and ran down the road."); try { Thread.sleep(3000); } catch (InterruptedException e) {e.printStackTrace(); } try { System.out.println(sdf.format(System.currentTimeMillis()) +": The car braked suddenly....");
                sdf.wait();
                System.out.println(sdf.format(System.currentTimeMillis()) + ": Car starts....");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(sdf.format(System.currentTimeMillis()) + ": The car came to the finish line");
        }
    }
}
private static class Ambulance implements Runnable {
    @Override
    public void run() {
        synchronized (sdf) {
            System.out.println(sdf.format(System.currentTimeMillis()) + ": Ambulance starts running on the road.");
            System.out.println(sdf.format(System.currentTimeMillis()) + ": Ambulance runs to the finish line"); }}}Copy the code

2. Result analysis

Call sdf.wait() on the Car thread; After that, the lock is released and the Ambulance thread can run with the lock. If it doesn’t wake up, the thread will block until it stops. For example, the SDF driver waited (), then threw away the car keys and stalled. We don’t get the keys back, we don’t get the car. Notify () is required to get the car keys

30:48: The car starts and runs on the road 30:51: the car brakes suddenly.... 30:51: The ambulance starts and runs on the road 30:51: the ambulance runs to the end and then it is blocked here and can't stop....Copy the code

3. Wake up the waiting thread

Note that wait and notify need to use the same object, otherwise there is no use waking up the Car thread after the Ambulance thread has run and then the Car gets ready

private static class Ambulance implements Runnable {
    @Override
    public void run() {
        synchronized (sdf) {
            System.out.println(sdf.format(System.currentTimeMillis()) + ": Ambulance starts running on the road.");
            System.out.println(sdf.format(System.currentTimeMillis()) + ": Ambulance runs to the finish line"); sdf.notify(); }}}Copy the code

4. Result analysis

40:23: The car starts and runs 40:26 on the road: the car brakes sharply.... Ambulance: Hey, buddy, wake up, you can drive... 40:26: The car starts.... 40:31: The car runs to the finish lineCopy the code

Four,Thread#join()Methods andThread#yield

1. Common code
public class Main6 {
    static SimpleDateFormat sdf = new SimpleDateFormat("mm:ss");

    public static void main(String[] args) {
        Thread car = new Thread(new Car());
        car.start();
        System.out.println(sdf.format(System.currentTimeMillis()) + ":main thread ends");

    }

    private static class Car implements Runnable {
        @Override
        public void run() {
            System.out.println(sdf.format(System.currentTimeMillis()) + ": The car started and ran down the road."); try { Thread.sleep(3000); } catch (InterruptedException e) {e.printStackTrace(); } System.out.println(sdf.format(System.currentTimeMillis()) +": The car came to the finish line"); }}}Copy the code

2. Result analysis

26:28: Main thread ends 26:31: The car runs to the endCopy the code

3. Use of join method

Blocks the current thread until the join thread terminates or times out

public class Main6 {
    static SimpleDateFormat sdf = new SimpleDateFormat("mm:ss");

    public static void main(String[] args) {
        Thread car = new Thread(new Car());
        car.start();
        try {
            car.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(sdf.format(System.currentTimeMillis()) + ":main thread ends");

    }

    private static class Car implements Runnable {
        @Override
        public void run() {
            System.out.println(sdf.format(System.currentTimeMillis()) + ": The car started and ran down the road."); try { Thread.sleep(3000); } catch (InterruptedException e) {e.printStackTrace(); } System.out.println(sdf.format(System.currentTimeMillis()) +": The car came to the finish line"); }}} - > [result] -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- for: the car to start, on the road run 31:56:31:56 car ran to the finish: the main threads to terminateCopy the code

4. Yield method test

Cede CPU scheduling rights to threads, and then grab them together. Running status -> Ready status

public class Main7 {
    public static void main(String[] args) {
        Thread car = new Car("car");
        Thread ambulance = new Car("Ambulance");
        car.start();
        ambulance.start();
    }

    private static class Car extends Thread {
        public Car(String name) {
            super(name);
        }

        @Override
        public void run() {
            for (int i = 0; i < 10; i++) {
                System.out.println(getName() + "--" + i);
                if (i == 5) {
                    yield();
                }
            }
        }
    }
}
Copy the code

Several sets of data are run, most of which meet the requirement that another thread execute after relinquish the scheduling right, and a few of which do not. So yield says I’m not in a hurry, I can pull, I can get out. But who will do it next is uncertain.


Five, the summary

1. Points to be added:

[-synchronized-] 2 [-synchronized-] 1 [-synchronized-] 2 Synchronized objects need to be consistent, otherwise they won’t lock, and that doesn’t work. Wait (3000), i.e., wake up the thread after 3s. 4. You can set the join timeout xxx.JOIN (3000), that is, the thread enters the ready state after 3s. NotifyAll: Attendants of the dark winter, servants, and soldiers, heed the call of Kel ‘thuzad!


2. Simple comparison
item The subordinate Whether to release the lock State to abnormal
sleep Thread static method NO blocking InterruptedException
wait Object public method YES Waiting queue IllegalMonitorStateException+InterruptedException
notify/notifyAll Object public method Synchronous queue IllegalMonitorStateException
join Thread public method NO blocking InterruptedException
yield Thread public method NO The executable state There is no