Common methods of multithreading

Posted by Tracer on Sat, 22 Jan 2022 04:13:54 +0100

Common methods of multithreading

start and run

First look at calling the run method

Code example:

package com.wxit.test02;

import lombok.extern.slf4j.Slf4j;

/**
 * @author wj
 * @date 2022.01.02 19:25
 */
@Slf4j(topic = "c.Test")
public class Test {

    public static void main(String[] args) {
        Thread thread = new Thread("t1") {
            @Override
            public void run() {
                log.debug("Start execution t1 thread ");
            }
        };

        thread.run();
        log.debug("The main thread is executing....");
    }
}

**Console output**

19:27:46.721 c.Test [main] - Start execution t1 thread 
19:27:46.742 c.Test [main] - The main thread is executing....

The program still runs in the main thread and executes synchronously

Call the start method

package com.wxit.test02;

import lombok.extern.slf4j.Slf4j;

/**
 * @author wj
 * @date 2022.01.02 19:25
 */
@Slf4j(topic = "c.Test")
public class Test {

    public static void main(String[] args) {
        Thread thread = new Thread("t1") {
            @Override
            public void run() {
                log.debug("Start execution t1 thread ");
            }
        };

        thread.start();
        log.debug("The main thread is executing....");
    }
}

Console output:

19:32:28.911 c.Test [main] - The main thread is executing....
19:32:28.911 c.Test [t1] - Start execution t1 thread 

You can see that the program is running in the t1 thread

Summary

  • Calling the run method directly is to execute the run method in the main thread without starting a new thread
  • Directly using start is to start a new thread and indirectly execute the code in run through the new thread

sleep and yield

sleep

  1. Calling sleep will make the current thread enter the Timed Waiting state (blocking) from Running
  2. Other threads can use the interrupt method to interrupt the sleeping thread, and the sleep method will throw an InterruptedException
  3. The thread after sleep may not be executed immediately
  4. It is recommended to use the sleep of TimeUnit instead of the sleep of Thread to obtain better readability

yield

  1. Calling yield will enable the current thread to enter the Runnable ready state from Running, and then schedule other threads.
  2. The specific implementation depends on the task scheduler of the operating system

thread priority

  • Thread priority will prompt the scheduler to schedule the thread first, but it is only a prompt, and the scheduler can ignore it
  • If the cpu is busy, the thread with higher priority will get more time slices, but when the cpu is idle, priority has little effect

Code example:

package com.wxit.test02;

/**
 * @author wj
 * @date 2022.01.02 19:40
 */
public class Test02 {
    public static void main(String[] args) {
        Runnable r1 = () -> {
            int count = 0;
            for (; ; ) {
                System.out.println("--------1" + count++);
            }
        };
        Runnable r2 = () -> {
            int count = 0;
            for (; ; ) {
//                Thread.yield();
                System.out.println("                --------2" + count++);
            }
        };

        Thread t1 = new Thread(r1, "t1");
        Thread t2 = new Thread(r2, "t2");

        t1.setPriority(Thread.MIN_PRIORITY);
        t2.setPriority(Thread.MAX_PRIORITY);

        t1.start();
        t2.start();
    }
}

Check the source code and find that there are three thread priorities

    /**
     * The minimum priority that a thread can have.
     */
    public final static int MIN_PRIORITY = 1;

   /**
     * The default priority that is assigned to a thread.
     */
    public final static int NORM_PRIORITY = 5;(Default Priority )

    /**
     * The maximum priority that a thread can have.
     */
    public final static int MAX_PRIORITY = 10;

join method

First, I'll explain why I want to use join

Case description: what is the result of implementation?

package com.wxit.test02;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.TimeUnit;

/**
 * @author wj
 * @date 2022.01.02 20:51
 */
@Slf4j(topic = "c.Test03")
public class Test03 {

    static int r = 0;
    public static void main(String[] args) {
        test01();
    }

    static private void test01(){
        log.debug("Start execution....");
        Thread t1 = new Thread(() -> {
            log.debug("Start execution in thread run method....");
            sleep(1);
            log.debug("End of sleep....");
            r = 10;
        });
        t1.start();
        log.debug("The result is:{}",r);
        log.debug("End of main thread execution");
    }

    public static void sleep(int i) {
        try {
            TimeUnit.SECONDS.sleep(i);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

Execution results:

20:58:02.833 c.Test03 [main] - Start execution....
20:58:02.886 c.Test03 [Thread-0] - Start execution in thread run method....
20:58:02.886 c.Test03 [main] - The result is:0
20:58:02.888 c.Test03 [main] - End of main thread execution
20:58:03.894 c.Test03 [Thread-0] - End of sleep....

Process finished with exit code 0

analysis

  • Because the main thread and thread t1 execute in parallel, thread t1 needs 1 second to calculate r=10
  • The main thread prints the result of R at the beginning, so it can only print r=0

resolvent

  • Use join to add T1 After start()

At T1 After start()

After calling the join method, the console output is:

21:01:12.347 c.Test03 [main] - Start execution....
21:01:12.388 c.Test03 [Thread-0] - Start execution in thread run method....
21:01:13.389 c.Test03 [Thread-0] - End of sleep....
21:01:13.389 c.Test03 [main] - The result is:10
21:01:13.389 c.Test03 [main] - End of main thread execution

Application synchronization

From the caller's point of view, if

  • You need to wait for the result to return before you can continue running, which is synchronization
  • It is asynchronous to continue running without waiting for the result to return

Wait for multiple results

Q: how many seconds does the following code take?

package com.wxit.test02;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.TimeUnit;

/**
 * @author wj
 * @date 2022.01.02 21:06
 */
@Slf4j(topic = "c.Test04")
public class Test04 {
    static int r1 = 0;
    static int r2 = 0;

    public static void main(String[] args) throws InterruptedException {
       log.debug("Start...");
        test01();
    }

    static private void test01() throws InterruptedException {
        Thread t1 = new Thread(() -> {
            sleep(1);
            r1 = 10;
        });
        Thread t2 = new Thread(() -> {
            sleep(2);
            r2 = 20;
        }, "t2");
        long start = System.currentTimeMillis();
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        long end = System.currentTimeMillis();
        log.debug("r1:{},r2:{},Spend time:{}",r1,r2,end - start);
    }

    public static void sleep(int i) {
        try {
            TimeUnit.SECONDS.sleep(i);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

The console output is as follows:

21:12:08.296 c.Test04 [main] - Start...
21:12:10.352 c.Test04 [main] - r1:10,r2:20,Spend time:2009

Topics: Java Back-end