First understanding of threads - understand the difference between wait and sleep and the running state transition process of threads

What is a thread

When a user starts a program, it actually starts a process, and then the thread belongs to the process. A process can create multiple threads. Threads are the basic unit of operating system scheduling. Each thread has its own local variables such as counters, heap, and stack. At present, the operating system executes multiple tasks concurrently. If it is in the case of a single CPU, it is to switch threads back and forth. The user feels that these tasks (threads) are executed at the same time.
java itself supports multithreading. When we start the main method, we actually open up a new thread to start. We can see the following demonstration code:

package com.ams.thread.lesson1;

import lombok.extern.slf4j.Slf4j;

import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;

/**
 * WeChat official account "AI code division" for source code and 2021 interview questions.
 * Demonstrate that java itself is multithreaded
 *
 * @author: AI Coder
 * Date: 2021/12/21 5:19 morning
 * Description:
 */
@Slf4j
public class Example1 {
    public static void main(String[] args) {
        ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
        ThreadInfo[] threadInfos = threadMXBean.dumpAllThreads(false, false);
        for (ThreadInfo threadInfo : threadInfos) {
            log.info("Current thread name:{}",threadInfo.getThreadName());
        }
    }
}

From the output results, we can see that five threads have been started, and the last thread is main, that is, the thread used to start our main method.

Why do I need to introduce threads

  • More processor cores

With the increasing number of CPU cores of computer processors, that is, our programs have more opportunities to win CPU resources. If our programs always run on a single thread, these CPU resources will be wasted. If multithreading technology is used, the program can distribute these tasks to different CPU cores for parallel processing.

  • Faster response time

After the introduction of multithreading, tasks are executed from serial execution to parallel programming, and the execution time can be significantly improved

How to understand concurrency and parallelism

  • Concurrent

Tasks are executed alternately. Only one task is executed at the same time. It is completed by switching through threads and exists in multiprocessors and single processors

  • parallel

Tasks are executed at the same time and stored in multiprocessors

Thread priority (just understand this concept)

Everything has a priority. In java threads, you can also set the priority to determine the number of time slices allocated to the thread at one time.
In java, the priority of threads is set through setProperty (Integer value), which is 5 by default. Threads with frequent IO blocking need to set a higher priority, and threads with long CPU consumption need to set a lower priority to ensure that the processor will not be monopolized by threads.
It should be noted that the processing of thread priority is different in different operating systems, and some operating systems will ignore this configuration. Therefore, we cannot rely too much on setting thread priority to ensure the final execution result.
Setting priorities through code validation takes effect

package com.ams.thread.lesson1;

import cn.hutool.core.thread.ThreadUtil;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * WeChat official account "AI code division" for source code and 2021 interview questions.
 * Verify that the thread priority setting is ignored
 *
 * @author: AI Coder
 * Date: 2021/12/21 5:19 morning
 * Description:
 */
@Slf4j
public class Example2 {
    private static volatile boolean start = false;
    private static volatile boolean end = false;


    public static void main(String[] args) {
        List<Job> jobs = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            Job job = new Job(i % 2 == 0 ? 1 : 10);
            jobs.add(job);
            new Thread(job).start();
        }
        start = true;
        ThreadUtil.sleep(10000);
        end = true;
        List<Job> sortJob = jobs.stream().sorted(new Comparator<Job>() {
            @Override
            public int compare(Job o1, Job o2) {
                return o1.count - o2.count;
            }
        }).collect(Collectors.toList());
        for (Job job : sortJob) {
            log.info("priority {} count: {}",job.priority,job.count);
        }

    }

    static class Job implements Runnable {
        private int priority;
        private int count;

        public Job(int property) {
            this.priority = property;
        }

        @Override
        public void run() {
            while (!start) {
                Thread.yield();
            }
            while (!end) {
                Thread.yield();
                count++;
            }
        }
    }
}

Output result: setting priority has no effect

Use jsatck tool to view the internal situation of the runtime thread

  • top locate process id
  • jstack pid enters the process to view the thread

Status of the thread

By running the following code, first look at the status of the thread

Demo code

package com.ams.thread.lesson1;

import cn.hutool.core.thread.ThreadUtil;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.TimeUnit;

/**
 * WeChat official account "AI code division" for source code and 2021 interview questions.
 * Test thread status
 *
 * @author: AI Coder
 * Date: 2021/12/21 5:19 morning
 * Description:
 */
@Slf4j
public class Example3 {
    public static void main(String[] args) {
        new Thread(new TimeWaitingThread(), "TimeWaitingThread").start();
        new Thread(new BlockedThread(), "BlockedThread-B").start();
        new Thread(new BlockedThread(), "BlockedThread-A").start();
        new Thread(new WaitingThread(), "WaitingThread").start();
    }

    static class TimeWaitingThread implements Runnable {
        @Override
        public void run() {
            while (true) {
                ThreadUtil.sleep(200, TimeUnit.SECONDS);
            }
        }
    }

    static class BlockedThread implements Runnable {
        @Override
        public void run() {
            synchronized (BlockedThread.class) {

                while (true) {
                    ThreadUtil.sleep(200, TimeUnit.SECONDS);
                }
            }
        }
    }

    static class WaitingThread implements Runnable {
        @Override
        public void run() {
            while (true) {
                synchronized (WaitingThread.class) {
                    try {
                        WaitingThread.class.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}

Print thread status

  • jps find the corresponding process (Example3)
  • Process pid corresponding to jstack

Thread state

  • NEW

When the state is first known, the thread is built, but the start method has not been called

  • RUNNABLE

The thread is in the ready and running state. After obtaining the CPU usage right, the thread will be in the ready state. After obtaining the CPU time slice, the thread will be in the running state.

  • BLOCKED

Thread blocking status: wait for other threads to release the lock

  • WAITING

The thread enters the infinite waiting state and needs to wait for other threads to wake up

  • TIME_WAITING

Timeout waiting status. It will wake up automatically after a specified period of time

  • TERMINATED

End of thread

The difference between sleep and wait

The difference between them is that sleep does not release the lock, while wait releases the lock

Verify sleep release lock

package com.ams.thread.lesson1;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.thread.ThreadUtil;
import lombok.extern.slf4j.Slf4j;

import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * WeChat official account "AI code division" for source code and 2021 interview questions.
 * Verify that sleep does not release the lock
 *
 * @author: AI Coder
 * Date: 2021/12/21 5:19 morning
 * Description:
 */
@Slf4j
public class Example4 {

    public static void main(String[] args) {
        new Thread(new SleepNotReleaseLockThread1()).start();
        ThreadUtil.sleep(1, TimeUnit.SECONDS);
        new Thread(new SleepNotReleaseLockThread2()).start();
    }
    static class SleepNotReleaseLockThread1 implements Runnable {
        @Override
        public void run() {
            synchronized (Example4.class) {
                System.out.println("Start time:" + DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
                ThreadUtil.sleep(5, TimeUnit.SECONDS);
                System.out.println("End time:" + DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
            }
        }
    }
    static class SleepNotReleaseLockThread2 implements Runnable {
        @Override
        public void run() {
            synchronized (Example4.class) {
                System.out.println("End time:" + DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
            }
        }
    }
}

It can be seen from the results that although thread 1 called sleep, thread 2 is still blocked and waiting for thread 1 to release the lock, so verifying that sleep will not release the lock

Verify wait release lock

package com.ams.thread.lesson1;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.thread.ThreadUtil;
import lombok.extern.slf4j.Slf4j;

import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * WeChat official account "AI code division" for source code and 2021 interview questions.
 * Verify wait release lock
 *
 * @author: AI Coder
 * Date: 2021/12/21 5:19 morning
 * Description:
 */
@Slf4j
public class Example5 {

    public static void main(String[] args) {
        new Thread(new WaitReleaseLockThread1()).start();
        ThreadUtil.sleep(1, TimeUnit.SECONDS);
        new Thread(new WaitReleaseLockThread2()).start();

    }
    static class WaitReleaseLockThread1 implements Runnable {
        @Override
        public void run() {
            synchronized (Example5.class) {
                System.out.println("WaitReleaseLockThread1 Start time:" + DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
                try {
                    Example5.class.wait(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("WaitReleaseLockThread1 End time:" + DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
            }
        }
    }
    static class WaitReleaseLockThread2 implements Runnable {
        @Override
        public void run() {
            synchronized (Example5.class) {
                System.out.println("WaitReleaseLockThread2 End time:" + DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
            }
        }
    }
}

It can be seen from the verification results that thread 2 did not wait for thread 1 to complete execution, which means that when thread 1 calls the wait method, the lock has been released, and thread 2 can obtain the lock. Therefore, the conclusion is that wait will release the lock

Thread state transition

Daemon thread

Daemon is a kind of daemon thread. After all business threads (non daemon threads) are finished, it will destroy itself and end the thread

package com.ams.thread.lesson1;

import cn.hutool.core.thread.ThreadUtil;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.TimeUnit;

/**
 * WeChat official account "AI code division" for source code and 2021 interview questions.
 * Validate Daemon thread
 *
 * @author: AI Coder
 * Date: 2021/12/21 5:19 morning
 * Description:
 */
@Slf4j
public class Example6 {

    public static void main(String[] args) {
        Thread thread = new Thread(new DaemonThread());
        thread.setDaemon(true);
        thread.start();

    }

    static class DaemonThread implements Runnable {
        @Override
        public void run() {
            ThreadUtil.sleep(3, TimeUnit.SECONDS);
            System.out.printf("daemon End of operation");
        }
    }
}

You can try to remove thread setDaemon(true); What's the difference between this setting and the output result?

Keywords: Java Back-end

Added by my8by10 on Fri, 31 Dec 2021 10:34:03 +0200