[Java Concurrent Programming] Java Multithreading (1): Thread Foundation

1. Thread introduction

1.1 Thread state

  • NEW (created): the thread has just been created, but has not been started, and start has not yet been called
  • RUNNABLE: The strat method is called; it may be executed on the CPU, or it may not
  • TIMED_WAITING (timed waiting): give up CPU, time to sleep; sleep (hold lock)
  • WAITINIT (wait): give up the CPU, sleep; park->unpark without lock, wait->notify with lock (lock will be released)
  • BLOCKED (blocking): waiting to obtain the monitor lock lock, is for synchronized
  • TERMINATED (terminated): the end of the operation; the child thread is completed, interrupted, or aborted

The following figure is a comparison of process status and Java thread status:

è¿ ™ é ‡ Œå † ™ å ›¾ç ‰ ‡ æ ???? è¿ °

1.2 Priority

The priority represents the size of the thread execution opportunity. The high priority may be executed first, and the low priority may be executed later. In the Java source code, the priority from low to high is 1 to 10, and the thread defaults to new priority. 5. The source code is as follows:

// 最低优先级
public final static int MIN_PRIORITY = 1; 

// 普通优先级,也是默认的
public final static int NORM_PRIORITY = 5;

// 最大优先级
public final static int MAX_PRIORITY = 10;

1.3 Daemon thread

The threads we create by default are non-daemon threads. When creating a daemon thread, you need to set the daemon attribute of Thread to true. The priority of the daemon thread is very low. When the JVM exits, it doesn’t care whether there is a daemon thread. Even if there are many daemon threads, the JVM will still exit . At work, we may write some tools to do some monitoring work. At this time, we all use guardian sub-threads to do so. Even if the monitoring throws an exception, because it is a sub-thread, it will not affect the main business thread. Because it is a daemon thread, the JVM does not need to pay attention to whether the monitoring is running, and it will exit when it exits, so it will not have any impact on the business.

1.4 A few notes

  • Threads run alternately (task>time slice), and now the CPU is often multi-core
  • main is the main thread, it may be executed ahead of time, generally do not block
  • Threads are independent of each other, when an exception is thrown, it will only affect the current thread
  • Thread.currentThread() current thread

2.*Thread creation & running

**Thread is equivalent to the carrier, to start must have a task (Callable/Runnable) **

2.1 Thread

For convenience, Thread has implemented Runnable, so you can directly inherit Thread and override the run method

class MyThread extends Thread{
    
    
  public void run() {
    
    ...}
}

2.2 Runnable

// 内部类
Thread thread = new Thread(new Runnable() {
    
    
  public void run() {
    
    ...}
});

// lamada
new Thread(()->{
    
    
    public void run() {
    
    ...}
}).start()

2.3 Callable

// Callable不能直接使用,而是包装成FutureTask 
FutureTask futureTask = new FutureTask(new Callable<T> () {
    
    
    public String call() throws Exception {
    
    ...}
  });
// FutureTask也是Runnable,所以可以传入Thread然后运行
new Thread(futureTask).start();
// 获取执行结果,无参会一直阻塞等待执行结果
futureTask.get()

-> start method source code

The start method can create a new thread, the internal is to call Runnable's run method

public synchronized void start() {
    
    
    // 如果没有初始化,抛异常
    if (threadStatus != 0)
        throw new IllegalThreadStateException();
    group.add(this);
    // started 是个标识符,我们在做一些事情的时候,经常这么写
    // 动作发生之前标识符是 false,发生完成之后变成 true
    boolean started = false;
    try {
    
    
        // 这里会创建一个新的线程,执行完成之后,新的线程已经在运行了,既 target 的内容已经在运行了
        start0();
        // 这里执行的还是主线程
        started = true;
    } finally {
    
    
        try {
    
    
            // 如果失败,把线程从线程组中删除
            if (!started) {
    
    
                group.threadStartFailed(this);
            }
         // Throwable 可以捕捉一些 Exception 捕捉不到的异常,比如说子线程抛出的异常
        } catch (Throwable ignore) {
    
    
            /* do nothing. If start0 threw a Throwable then
              it will be passed up the call stack */
        }
    }
}
// 开启新线程使用的是 native 方法
private native void start0();

3. Thread control

3.1 Thread.sleep

  • The thread enters Timed_Waiting, the current thread sleeps, releases the CPU, and waits with the lock
  • effect
    • Simulate tasks; prevent multi-threaded tasks <time slice, thread serial execution
    • Pause the thread; pause the thread while it is running, and let the remaining threads run
  • TimeUnit.SECONDS.sleep(2)

3.2 Thread.yeild

  • The current thread gives up the CPU, enters the NEW state, and competes for the CPU again
  • Role: to prevent the current thread from occupying the CPU
  • Difference from sleep
    • sleep can specify the waiting time
    • During sleep, all levels of threads can run, yeild generally only allows threads with high priority to run

3.3 Thread.interrput

  • Setting thread interruption does not affect the continued execution of the thread
  • But after the thread is set to sleep (wait, jion, sleep), an InterruptedException is thrown, and the interrupt flag is cleared and reset to false
  • Thread.currentThread().isInterrupted()

3.4 obj.wait

  • The thread enters WAITING, releases the lock of the current object, and waits to be awakened
  • Must be used in a synchronized code block, first hold the lock
    • Essence: Java thread communication is essentially shared memory , rather than direct communication
    • Representation: wait, notify need to call the monitor object
  • Generally used with while
    • After being awakened, it will compete for the lock again, and then restart from the last wait position
    • While judged multiple times to prevent the object from being modified during the wait period

3.5 obj.notify(All)

  • Randomly wake up waiting threads
  • Must be used in synchronized code block
  • After the current thread runs to release the lock, the awakened thread will compete for the lock again
  • In the producer-consumer model, notifyAll is recommended, because the thread awakened by notify is not sure whether it is a producer or a consumer

3.6 obj.join

  • The current thread will wait for the end of the thread calling join before continuing to run
  • Essence: In fact, the current thread function wait, notify after the calling thread runs
  • effect
    • When the amount of thread tasks is large, ensure that the main thread ends after these threads run.
    • Control the order of execution among sub-threads

3.7 LockSupport.park

  • Make the specified thread enter WAITING without obtaining the lock, sleep and release the CPU
  • Need to specify the wake-up thread by unpark
  • Difference comparison:
    • wait: unpark(th) can wake up the specified thread, and notify is to wake up randomly
    • yeild: park enters the dormant state and no longer preempts the CPU, while yeild just yields and participates in the next CPU competition
    • interrput: interrput will not affect thread execution before the thread sleeps
  • park is defined in UNSAFE, generally called by LockSupport

Guess you like

Origin blog.csdn.net/weixin_43935927/article/details/108606971