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
- Calling sleep will make the current thread enter the Timed Waiting state (blocking) from Running
- Other threads can use the interrupt method to interrupt the sleeping thread, and the sleep method will throw an InterruptedException
- The thread after sleep may not be executed immediately
- It is recommended to use the sleep of TimeUnit instead of the sleep of Thread to obtain better readability
yield
- Calling yield will enable the current thread to enter the Runnable ready state from Running, and then schedule other threads.
- 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