1. Threads and processes
Process refers to an application running in memory, and the memory space of each process is independent. It can be understood that each process has its own heap and stack area, and their memory space is not shared by default.
Thread refers to the execution path in a process. Multithreading refers to multiple execution paths in a process. The content between threads can be shared, and threads can switch freely and execute concurrently. It is worth noting that a process has at least one thread.
Threads can be regarded as a smaller division of processes, and the concurrent execution of threads does not mean that multiple threads run at the same time, but because the CPU has a time-sharing mechanism, each thread can cycle to obtain its own CPU time slice. Because the CPU executes very fast, all threads seem to be running at the same time.
The role of threads is to allow the CPU to do multiple things at the same time, and its execution depends on thread scheduling. yes:
Time sharing scheduling: all threads use the right to use the CPU in turn, and allocate the CPU time of each thread equally;
Preemptive scheduling: give priority to the threads with high priority to use the CPU. Java uses this scheduling, but it does not mean that the threads with the highest priority must execute first. It can only be said that the threads with high priority have a greater probability of executing first.
Multithreading does not improve the execution speed of CPU, but improves the efficiency of CPU.
2. Synchronous and asynchronous
Frankly understand that synchronization is queued and asynchrony is simultaneous, while synchronization efficiency is low but safe, and asynchrony efficiency is high but unsafe.
Concurrency means that multiple events occur within a specified time period, and parallelism means that multiple events occur at the same time.
3. Create thread
There are three ways
1) Method 1: inherit Thread method
Step 1: declare the sub Thread class, inherit the Thread method, override the run method, and specify the task to be executed in the run method body;
Step 2: create a new sub thread object and create a sub thread task;
Step 3: call the start method to start the thread task.
Code example:
public class ThreadDemo { public static void main(String[] args) { //Create a thread task without specifying a thread name MyThread m1 = new MyThread(); //Set the thread name or not m1.setName("This is the specified word thread name"); //Start child thread m1.start(); //Main thread loop for (int i = 0; i < 5; i++) { //Get the current thread name and output the corresponding number System.out.println(Thread.currentThread().getName()+i); try { Thread.sleep(200); }catch (InterruptedException e) { e.printStackTrace(); } } } } class MyThread extends Thread{ @Override public void run() { for (int i = 0; i < 5; i++) { System.out.println(Thread.currentThread().getName()+i); try { //Wait 200 ms Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } } } }
Operation results:
[external chain picture transfer failed. The source station may have anti-theft chain mechanism. It is recommended to save the picture and upload it directly (img-trnh5vfh-1631103914043)( file:///C: \Users\Dell\AppData\Local\Temp\msohtmlclip1\01\clip_image002.jpg)]
2) Method 2: implement Runnable interface (common)
Step 1: declare the sub thread class and implement the Runnable interface, rewrite the run method, and specify the tasks to be executed in the run method body;
Step 2: create a new sub thread object to create a task;
Step 3: create a thread object, pass in the task, and give the name of the sub thread;
Step 4: call the start method to start the thread task.
public class ThreadDemo { public static void main(String[] args) { //Create thread task MyThread m1 = new MyThread(); //Create a thread object, pass in the task and set the thread name, or do not set the thread name Thread t1 = new Thread(m1,"Child thread name"); //Start thread t1.start(); //Main thread loop for (int i = 0; i < 5; i++) { //Get the current thread name and output the corresponding number System.out.println(Thread.currentThread().getName()+i); try { Thread.sleep(200); }catch (InterruptedException e) { e.printStackTrace(); } } } } class MyThread implements Runnable{ @Override public void run() { for (int i = 0; i < 5; i++) { System.out.println(Thread.currentThread().getName()+i); try { //Wait 200 ms Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } } } }
Operation results:
[external chain picture transfer failed. The source station may have anti-theft chain mechanism. It is recommended to save the picture and upload it directly (img-cvleoqsw-1631103914053)( file:///C: \Users\Dell\AppData\Local\Temp\msohtmlclip1\01\clip_image004.jpg)]
3) Method 3: callable with return value (basically not used)
Step 1: define the callable implementation class and rewrite the call method;
Step 2: create a task using FutureTask class and pass in the callable implementation class object;
Step 3: create a Thread and pass in the task;
Step 4: start the child thread
import java.util.concurrent.*; public class CallaDemo { public static void main(String[] args) { Callable<Integer> c = new Callable<Integer>() { @Override public Integer call() throws Exception { Thread.sleep(1000); System.out.println("The child thread is executing"); return 100; } }; FutureTask<Integer> task = new FutureTask<>(c); new Thread(task).start(); try { try{ int num = task.get(2000, TimeUnit.MILLISECONDS); } catch (TimeoutException e) { e.printStackTrace(); } } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } System.out.println("The main thread is executing"); } }
Operation results:
[the external chain picture transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the picture and upload it directly (img-3bepe90d-1631103914056)( file:///C: \Users\Dell\AppData\Local\Temp\msohtmlclip1\01\clip_image006.jpg)]
In the main method, if you want to accept the return value of callable, the main thread will wait for the child thread to finish executing or return an exception before continuing to execute.
If the main thread needs the return value of the child thread and does not want to wait, you can call the isDone method to determine whether the child thread ends.
4) The difference between inheriting Threa class and implementing Runnable
The essence of both is to start the thread by calling the start method. The run method is then executed automatically. However, inheritance can only be single inheritance, which is not conducive to expansion, while the implementation interface can implement multiple interfaces, which is more conducive to expansion.
4. Wire program lock
Thread lock is mainly used to solve the data disorder problem of heap memory shared by multiple threads.
It is divided into display lock and implicit lock. The display lock is implemented through class ReentrantLock. lock() and unlock() methods are called at the beginning and end of the code block to be synchronized to lock and unlock. The implicit lock uses synchronized to synchronize. The following focuses on its learning.
A typical ticket selling case, when thread lock is not used, the code is:
public class LockDemo { public static void main(String[] args) { Myrun m1 = new Myrun(); new Thread(m1,"Ticket channel 1").start(); new Thread(m1,"Ticket channel 2").start(); new Thread(m1,"Ticket channel 3").start(); } } class Myrun implements Runnable{ int ticket = 5; @Override public void run() { for (int i=0;i<10;i++) { if(ticket > 0) { System.out.println(Thread.currentThread().getName() + "Preparing to issue tickets, please wait......."); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "Ticket issued successfully! Remaining tickets:" + --ticket); } } } }
Operation results:
[external chain picture transfer failed. The source station may have anti-theft chain mechanism. It is recommended to save the picture and upload it directly (img-6j66ydxt-1631103914061)( file:///C: \Users\Dell\AppData\Local\Temp\msohtmlclip1\01\clip_image008.jpg)]
It can be seen from the results that even if there is a judgment on the number of votes, the remaining votes are still negative. The reason is that one thread in the multi thread has not been completed and other threads have been, resulting in data reading errors. A good way to solve this problem is to add thread lock.
It is to lock the code to be synchronized so that only one thread can enter the corresponding code.
There are also two methods, as follows:
1) Use synchronized code blocks:
public class LockDemo { public static void main(String[] args) { Myrun m1 = new Myrun(); new Thread(m1,"Ticket channel 1").start(); new Thread(m1,"Ticket channel 2").start(); new Thread(m1,"Ticket channel 3").start(); } } class Myrun implements Runnable{ private int ticket = 6; @Override public void run() { while(true) { synchronized (this) { if (this.ticket > 0) { try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "Ticket issued successfully! Remaining tickets:" + --ticket); } else{ break; } } } } }
Operation results:
[external chain picture transfer failed. The source station may have anti-theft chain mechanism. It is recommended to save the picture and upload it directly (img-qk6mgevb-1631103914064)( file:///C: \Users\Dell\AppData\Local\Temp\msohtmlclip1\01\clip_image010.jpg)]
2) Use synchronization method
This method actually encapsulates the code in the synchronization code block in one method, as follows:
public class LockDemo { public static void main(String[] args) { Myrun m1 = new Myrun(); Thread t1 = new Thread(m1,"Ticket channel 1"); Thread t2 = new Thread(m1,"Ticket channel 2"); Thread t3 = new Thread(m1,"Ticket channel 3"); //Set thread priority t1.setPriority(Thread.MIN_PRIORITY); t2.setPriority(Thread.MAX_PRIORITY); t3.setPriority(Thread.MAX_PRIORITY); t3.start(); t1.start(); t2.start(); } } class Myrun implements Runnable{ private int ticket = 6; boolean flag = true; @Override public void run() { while(flag) { flag = sale(); } } public synchronized boolean sale(){ if (this.ticket > 0) { try { Thread.sleep(500); }catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "Ticket issued successfully! Remaining tickets:" + --ticket); return true; }else{ return false; } } }
Operation results:
[external chain picture transfer failed. The source station may have anti-theft chain mechanism. It is recommended to save the picture and upload it directly (img-adofp9bi-1631103914067)( file:///C: \Users\Dell\AppData\Local\Temp\msohtmlclip1\01\clip_image012.jpg)]
3) Deadlock
Deadlock means that when two or more threads execute synchronous code, they need to wait for the end of each other's synchronous code block at the same time, so that the thread is blocked and cannot continue to execute.
5. Thread state
Create (new thread) - > ready (the thread has been started and will enter the thread queue to wait for CPU service) - > run (the thread is called and obtains processor resources) - > blocked (the thread is suspended and will stain the CPU and temporarily terminate its execution, such as calling suspend(), wait(), sleep()) Method, when the thread is blocked, it cannot enter the queue. It can only enter the ready state after the cause of the blockage is clear, such as wake-up: notify();notifyAll();) - > termination (the thread runs and cannot continue running).
6. Thread interrupt
The obsolete interrupt method is stop, but this method is not used now. The reason is that if a thread is directly interrupted externally, the resources occupied by the thread may not be released in time, and even exceptions may be thrown. The correct operation of interrupt thread is to add an interrupt flag to the thread, interrupt(); Then, processing can be added to the exception capture code block to end the thread or perform other operations. Code example:
public class ThreadDemo { public static void main(String[] args) { //Create thread task MyThread m1 = new MyThread(); //Create a thread object, pass in the task and set the thread name, or do not set the thread name Thread t1 = new Thread(m1,"Child thread name"); //Start thread t1.start(); //Main thread loop for (int i = 0; i < 5; i++) { //Get the current thread name and output the corresponding number System.out.println(Thread.currentThread().getName()+i); try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } } //Add interrupt flag to thread t1 t1.interrupt(); } } class MyThread implements Runnable{ @Override public void run() { for (int i = 0; i < 10; i++) { System.out.println(Thread.currentThread().getName()+i); try { //Wait 200 ms Thread.sleep(200); } catch (InterruptedException e) { System.out.println("Exception flag found, thread ended"); break; } } } }
Operation results:
[external chain picture transfer failed. The source station may have anti-theft chain mechanism. It is recommended to save the picture and upload it directly (img-rmskjhej-1631103914068)( file:///C: \Users\Dell\AppData\Local\Temp\msohtmlclip1\01\clip_image014.jpg)]
7. Thread pool
There are four kinds of thread pools in Java: cache thread pool, fixed length thread pool, single thread pool and periodic fixed length thread pool
1) Cache thread pool:
The length can be changed. First judge whether there are idle threads in the thread pool. If there are, use it. If not, create it:
import java.util.concurrent.Executor; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class ThreadPoolDemo { public static void main(String[] args) { ExecutorService ecs = Executors.newCachedThreadPool(); ecs.execute(new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName()+"Heavenly King covering the earth tiger"); } }); ecs.execute(new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName()+"pagoda will stop river monster"); } }); try { Thread.sleep(1000); }catch (InterruptedException e) { e.printStackTrace(); } ecs.execute(new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName()+"Riverside Scene at Qingming Festival"); } }); } }
Operation results:
[the external chain picture transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the picture and upload it directly (img-hda3vkvv-1631103914070)( file:///C: \Users\Dell\AppData\Local\Temp\msohtmlclip1\01\clip_image016.jpg)]
As a result, when executing the third thread task, the original pool-1-thread-2 thread in the thread pool is used.
2) Fixed length linear pool:
The length of the thread pool is fixed. When executing a task, if there are idle threads, they will execute, otherwise they will wait.
The creation method is:
ExecutorService ecs = Executors.newFixedThreadPool(2);
3) Single thread pool:
There is only one thread in the thread pool. The creation method is:
ExecutorService ecs = Executors.newSingleThreadExecutor();
4) Periodic fixed length linear pool
There are two modes, one is to execute regularly, and the other is to execute non-stop tasks periodically, as follows:
import java.util.concurrent.*; public class ThreadPoolDemo { public static void main(String[] args) { ScheduledExecutorService secs = Executors.newScheduledThreadPool(2); /**Execute once regularly: \* Parameter 1: scheduled tasks \* Parameter 2: delay time \* Parameter 3: time unit */ secs.schedule(new Runnable() { @Override public void run() { System.out.println("Heavenly King covering the earth tiger"); } },3,TimeUnit.SECONDS); /**Cycle execution task \* Parameter 1: task \* Parameter 2: delay time at the first execution \* Parameter 3: cycle time quantity \* Parameter 4: time unit */ secs.scheduleAtFixedRate(new Runnable() { @Override public void run() { System.out.println("Riverside Scene at Qingming Festival"); } },5,1,TimeUnit.SECONDS); } }
*/
secs.schedule(new Runnable() {
@Override
public void run() {
System.out.println("Heavenly King covers the earth and tiger");
}
},3,TimeUnit.SECONDS);
/ * * cycle execution task
* parameter 1: task
* parameter 2: delay time at the first execution
* parameter 3: cycle time quantity
* parameter 4: time unit
*/
secs.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
System.out.println("Qingming River map");
}
},5,1,TimeUnit.SECONDS);
}
}