It's enough to read this article in Java multithreading (detailed summary of hematemesis)

Posted by jasondavis on Thu, 28 Nov 2019 08:43:26 +0100

Processes and threads

A process is a dynamic execution process of a program. It needs to go through a complete process from code loading, code execution to the completion of execution. This process is also a process from the generation, development to final extinction of the process itself. The multiprocess operating system can run multiple processes (programs) at the same time. Because the CPU has a time-sharing mechanism, each process can cycle to get its own CPU time slice. Because the CPU is very fast, all programs seem to be running at the same time.

Multithreading is an effective way to implement concurrency mechanism. Processes, like threads, are a basic unit of concurrency. Thread is a smaller execution unit than process, and it is further divided on the basis of process. The so-called multithreading refers to that a process can produce multiple smaller program units in the execution process. These smaller units are called threads. These threads can exist and run at the same time. A process may contain multiple threads executing at the same time. The difference between process and thread is shown as follows:

How to implement threads in Java

There are two ways to implement multithreading in Java, one is to inherit the Thread class, the other is to implement the Runnable interface. Let's introduce the use of these two methods.

Implement the Runnable interface

 1 package ljz; 
 2 class MyThread implements Runnable{ // Realization Runnable Interface, as the implementation class of thread 
 3     private String name ;       // Represents the name of the thread 
 4     public MyThread(String name){ 
 5         this.name = name ;      // Configuration by construction method name attribute 
 6     } 
 7     public void run(){  // Overwrite run()Method as the operation body of the thread 
 8         for(int i=0;i<10;i++){ 
 9             System.out.println(name + "Function, i = " + i) ; 
10         } 
11     } 
12 }; 
13 public class RunnableDemo01{ 
14     public static void main(String args[]){ 
15         MyThread mt1 = new MyThread("thread A ") ;    // Instanced object 
16         MyThread mt2 = new MyThread("thread B ") ;    // Instanced object 
17         Thread t1 = new Thread(mt1) ;       // instantiation Thread Class object 
18         Thread t2 = new Thread(mt2) ;       // instantiation Thread Class object 
19         t1.start() ;    // Start multithreading 
20         t2.start() ;    // Start multithreading 
21     } 
22 };

Program run result:

Inherit Thread class

 1 class MyThread extends Thread{  // inherit Thread Class as the implementation class of thread 
 2     private String name ;       // Represents the name of the thread 
 3     public MyThread(String name){ 
 4         this.name = name ;      // Configuration by construction method name attribute 
 5     } 
 6     public void run(){  // Overwrite run()Method as the operation body of the thread 
 7         for(int i=0;i<10;i++){ 
 8             System.out.println(name + "Function, i = " + i) ; 
 9         } 
10     } 
11 }; 
12 public class ThreadDemo02{ 
13     public static void main(String args[]){ 
14         MyThread mt1 = new MyThread("thread A ") ;    // Instanced object 
15         MyThread mt2 = new MyThread("thread B ") ;    // Instanced object 
16         mt1.start() ;   // Calling thread body 
17         mt2.start() ;   // Calling thread body 
18     } 
19 };

Program run result:

It can be seen from the program that the two thread objects are running alternately, which thread object has seized the CPU resources, which thread can run, so the running result of the program is definitely different each time. Although the start() method is called at the start of the thread, it actually calls the main body defined by the run() method.

Thread class and Runnable interface

Multithreading can be realized by Thread class and running interface. What are the relations and differences between them? Let's look at the definition of the Thread class.

public class Thread extends Object implements Runnable

From the definition of the Thread class, it can be clearly found that the Thread class is also a subclass of the Runnable interface, but the run() method in the Runnable interface is not fully implemented in the Thread class. Here is a partial definition of the Thread class.

 1 Private Runnable target; 
 2 public Thread(Runnable target,String name){ 
 3     init(null,target,name,0); 
 4 } 
 5 private void init(ThreadGroup g,Runnable target,String name,long stackSize){ 
 6     ... 
 7     this.target=target; 
 8 } 
 9 public void run(){ 
10     if(target!=null){ 
11         target.run(); 
12     } 
13 }

It can be found from the definition that the run() method in the Thread class calls the run() method in the Runnable interface, that is to say, this method is completed by the Runnable subclass, so if you want to implement multithreading by inheriting the Thread class, you must override run().

In fact, there are also differences between Thread class and Runnable interface in use. If a class inherits Thread class, it is not suitable for multiple threads to share resources. If Runnable interface is implemented, it is convenient to share resources.

Thread state change

To implement multithreading, a new thread object must be created in the main thread. Any thread generally has five states: create, ready, run, block and terminate. Here are the States:

  • Create status

After a Thread object is created with the construction method in the program, the new Thread object will be in the new state. At this time, it has the corresponding memory space and other resources, but it is still in the non operational state. To create a new Thread object, you can use the Thread class construction method, such as "Thread thread=new Thread()".

  • Ready state

After a new thread object is created, the thread can be started by calling the start() method of the thread. When the thread starts, the thread enters the ready state. At this point, the thread will enter the thread queue and wait for the CPU service, which indicates that it has the running conditions.

  • Operation status

When the ready state is called and the processor resource is obtained, the thread enters the running state. At this point, the run() method of the thread object is automatically called. The run() method defines the operations and functions of the thread.

  • Blocking status

In some special cases, if a thread is suspended or needs to execute time-consuming I / O operations, the CPU will temporarily suspend its execution and enter a blocking state. In the executable state, if sleep(),suspend(),wait() and other methods are called, the threads will enter the blocking state. In case of blocking, the threads cannot enter the queue. Only when the cause of blocking is eliminated, the threads can enter the ready state.

  • State of death

When a thread calls the stop() method or the run() method is executed, it is in a dead state. A thread in a dead state does not have the ability to continue.

Here is a question: how many threads does a Java program start at least at a time?

Answer: start at least two threads. Whenever a class is executed with Java command, a JVM will actually be started. Each JVM actually starts a thread in the operating system. Java itself has a garbage collection mechanism. So at least two threads will be started when Java is running, one is the main thread, and the other is the garbage collection thread.

Gets and sets the name of the thread

 1 class MyThread implements Runnable{ //Realization Runnable Interface 
 2     public void run(){ 
 3        for(int i=0;i<3;i++){ 
 4            System.Out.Println(Thread.currentThread().getName()+"Function, i="+i);  //Gets the name of the current thread 
 5        } 
 6   } 
 7 }; 
 8 
 9 public class ThreadDemo{ 
10 public static void main(String args[]){ 
11     MyThread my=new MyThread();  //Definition Runnable Subclass objects 
12     new Thread(my).start;    //The system automatically sets the thread name 
13     new Thread(my,"thread A").start();  //Set thread name manually 
14   } 
15 };   

Program run result:


Operation method of thread

As mentioned in the analysis of the working principle of custom mode, if you want to change the default configuration of Glide

Forced running of threads

In the thread operation, you can use the join() method to force a thread to run. During the forced running of a thread, other threads cannot run. You must wait for the thread to finish before you can continue to execute.

 1 class MyThread implements Runnable{ // Realization Runnable Interface 
 2     public void run(){  // Overwrite run()Method 
 3         for(int i=0;i<50;i++){ 
 4             System.out.println(Thread.currentThread().getName() 
 5                     + "Function, i = " + i) ;  // Gets the name of the current thread 
 6         } 
 7     } 
 8 }; 
 9 public class ThreadJoinDemo{ 
10     public static void main(String args[]){ 
11         MyThread mt = new MyThread() ;  // instantiation Runnable Subclass objects 
12         Thread t = new Thread(mt,"thread");     // instantiation Thread object 
13         t.start() ; // Startup thread 
14         for(int i=0;i<50;i++){ 
15             if(i>10){ 
16                 try{ 
17                     t.join() ;  // Thread forced 
18                 }catch(InterruptedException e){
19                 } 
20             } 
21             System.out.println("Main Thread running --> " + i) ; 
22         } 
23     } 
24 };

Program run result:


Thread sleep

A thread is allowed to sleep temporarily in the program. You can sleep directly by using Thread.sleep().

 1 class MyThread implements Runnable{ // Realization Runnable Interface 
 2     public void run(){  // Overwrite run()Method 
 3         for(int i=0;i<50;i++){ 
 4             try{ 
 5                 Thread.sleep(500) ; // Thread dormancy 
 6             }catch(InterruptedException e){
 7             } 
 8             System.out.println(Thread.currentThread().getName() 
 9                     + "Function, i = " + i) ;  // Gets the name of the current thread 
10         } 
11     } 
12 }; 
13 public class ThreadSleepDemo{ 
14     public static void main(String args[]){ 
15         MyThread mt = new MyThread() ;  // instantiation Runnable Subclass objects 
16         Thread t = new Thread(mt,"thread");     // instantiation Thread object 
17         t.start() ; // Startup thread 
18     } 
19 };

Program execution result:


Interrupt thread

When a thread is running, another thread can interrupt its running state directly through the interrupt() method.

 1 class MyThread implements Runnable{ // Realization Runnable Interface 
 2     public void run(){  // Overwrite run()Method 
 3         System.out.println("1,Get into run()Method") ; 
 4         try{ 
 5             Thread.sleep(10000) ;   // Thread sleep for 10 seconds 
 6             System.out.println("2,Sleep completed") ; 
 7         }catch(InterruptedException e){ 
 8             System.out.println("3,Sleep aborted") ; 
 9             return ; // Return to use 
10         } 
11         System.out.println("4,run()Normal end of method") ; 
12     } 
13 }; 
14 public class ThreadInterruptDemo{ 
15     public static void main(String args[]){ 
16         MyThread mt = new MyThread() ;  // instantiation Runnable Subclass objects 
17         Thread t = new Thread(mt,"thread");     // instantiation Thread object 
18         t.start() ; // Startup thread 
19         try{ 
20             Thread.sleep(2000) ;    // Thread sleep for 2 seconds 
21         }catch(InterruptedException e){ 
22             System.out.println("3,Sleep aborted") ; 
23         } 
24         t.interrupt() ; // Interrupt thread execution 
25     } 
26 };

The result of program running is:


Background thread

In a Java program, as long as there is a thread running in the foreground, the entire Java process will not disappear, so you can set a background thread at this time, so that even if the Java thread ends, the background thread will continue to execute. To achieve such an operation, you can directly use the setDaemon() method.

 1 class MyThread implements Runnable{ // Realization Runnable Interface 
 2     public void run(){  // Overwrite run()Method 
 3         while(true){ 
 4             System.out.println(Thread.currentThread().getName() + "In operation.") ; 
 5         } 
 6     } 
 7 }; 
 8 public class ThreadDaemonDemo{ 
 9     public static void main(String args[]){ 
10         MyThread mt = new MyThread() ;  // instantiation Runnable Subclass objects 
11         Thread t = new Thread(mt,"thread");     // instantiation Thread object 
12         t.setDaemon(true) ; // This thread runs in the background 
13         t.start() ; // Startup thread 
14     } 
15 };

In the process class MyThread, although the method run() is in the form of a dead loop, the program can still execute because the thread operation of the dead loop in the method has been set to run in the background.

thread priority

In the Java thread operation, all threads will remain in the ready state before running. At this time, which thread has the highest priority may be executed first.

 1 class MyThread implements Runnable{ // Realization Runnable Interface 
 2     public void run(){  // Overwrite run()Method 
 3         for(int i=0;i<5;i++){ 
 4             try{ 
 5                 Thread.sleep(500) ; // Thread dormancy 
 6             }catch(InterruptedException e){
 7             } 
 8             System.out.println(Thread.currentThread().getName() 
 9                     + "Function, i = " + i) ;  // Gets the name of the current thread 
10         } 
11     } 
12 }; 
13 public class ThreadPriorityDemo{ 
14     public static void main(String args[]){ 
15         Thread t1 = new Thread(new MyThread(),"thread A") ;  // Instantiate thread object 
16         Thread t2 = new Thread(new MyThread(),"thread B") ;  // Instantiate thread object 
17         Thread t3 = new Thread(new MyThread(),"thread C") ;  // Instantiate thread object 
18         t1.setPriority(Thread.MIN_PRIORITY) ;   // Lowest priority 
19         t2.setPriority(Thread.MAX_PRIORITY) ;   // Highest priority 
20         t3.setPriority(Thread.NORM_PRIORITY) ;  // Highest priority 
21         t1.start() ;    // Startup thread 
22         t2.start() ;    // Startup thread 
23         t3.start() ;    // Startup thread 
24     } 
25 };

Program run result:


It can be observed from the running results of the program that the thread will decide which thread will run first according to its priority, but it should be noted that the higher the priority is, the higher the priority is, the first execution will be determined by the CPU scheduling.

Thread comity

In the thread operation, you can also use the yield() method to temporarily give up the operation of one thread to other threads for execution

 1 class MyThread implements Runnable{ // Realization Runnable Interface 
 2     public void run(){  // Overwrite run()Method 
 3         for(int i=0;i<5;i++){ 
 4             try{ 
 5                 Thread.sleep(500) ; 
 6             }catch(Exception e){
 7             } 
 8             System.out.println(Thread.currentThread().getName() 
 9                     + "Function, i = " + i) ;  // Gets the name of the current thread 
10             if(i==2){ 
11                 System.out.print("Thread Courtesy:") ; 
12                 Thread.currentThread().yield() ;    // Thread comity 
13             } 
14         } 
15     } 
16 }; 
17 public class ThreadYieldDemo{ 
18     public static void main(String args[]){ 
19         MyThread my = new MyThread() ;  // instantiation MyThread object 
20         Thread t1 = new Thread(my,"thread A") ; 
21         Thread t2 = new Thread(my,"thread B") ; 
22         t1.start() ; 
23         t2.start() ; 
24     } 
25 };

Program execution result:


Synchronization and deadlock

If a multithreaded program is implemented through the Runnable interface, it means that the properties in the class are shared by multiple threads, which will cause a problem. If these multiple threads want to operate the same resource, the problem of resource synchronization may occur.

resolvent:

Sync code block

1 synchronized 
2 code to be synchronized 
3 }
 1 class MyThread implements Runnable{ 
 2     private int ticket = 5 ;    // Suppose there are five tickets 
 3     public void run(){ 
 4         for(int i=0;i<100;i++){ 
 5             synchronized(this){ // To synchronize the current object 
 6                 if(ticket>0){   // There are still tickets. 
 7                     try{ 
 8                         Thread.sleep(300) ; // Accession delay 
 9                     }catch(InterruptedException e){ 
10                         e.printStackTrace() ; 
11                     } 
12                     System.out.println("Selling tickets: ticket = " + ticket-- ); 
13                 } 
14             } 
15         } 
16     } 
17 }; 
18 public class SyncDemo02{ 
19     public static void main(String args[]){ 
20         MyThread mt = new MyThread() ;  // Defining Thread objects 
21         Thread t1 = new Thread(mt) ;    // Definition Thread object 
22         Thread t2 = new Thread(mt) ;    // Definition Thread object 
23         Thread t3 = new Thread(mt) ;    // Definition Thread object 
24         t1.start() ; 
25         t2.start() ; 
26         t3.start() ; 
27     } 
28 };

Program execution result:


Synchronization method

In addition to setting the required code as a synchronized block, you can also use the synchronized keyword to declare a method as a synchronized method.

1 synchronized method return value method name (parameter list) 
2 
3 }
 1 class MyThread implements Runnable{ 
 2     private int ticket = 5 ;    // Suppose there are five tickets 
 3     public void run(){ 
 4         for(int i=0;i<100;i++){ 
 5             this.sale() ;   // Call synchronization method 
 6         } 
 7     } 
 8     public synchronized void sale(){    // Declare synchronization method 
 9         if(ticket>0){   // There are still tickets. 
10             try{ 
11                 Thread.sleep(300) ; // Accession delay 
12             }catch(InterruptedException e){ 
13                 e.printStackTrace() ; 
14             } 
15             System.out.println("Selling tickets: ticket = " + ticket-- ); 
16         } 
17 
18     } 
19 }; 
20 public class SyncDemo03{ 
21     public static void main(String args[]){ 
22         MyThread mt = new MyThread() ;  // Defining Thread objects 
23         Thread t1 = new Thread(mt) ;    // Definition Thread object 
24         Thread t2 = new Thread(mt) ;    // Definition Thread object 
25         Thread t3 = new Thread(mt) ;    // Definition Thread object 
26         t1.start() ; 
27         t2.start() ; 
28         t3.start() ; 
29     } 
30 };

Program execution result:


From the result of the program running, we can see that this code has completed the same function as the previous synchronization code.

deadlock

Synchronization can ensure the correctness of resource sharing operation, but too much synchronization can also cause problems. For example, now Zhang San wants Li Si's paintings, Li Si wants Zhang San's books. Zhang San says to Li Si, "give me your paintings, and I'll give you books." Li Si also says to Zhang San, "give me your books, and I'll draw for you." the two people wait for each other to act first, and do so without any result. This is actually the concept of deadlock.

The so-called deadlock is that two threads are waiting for each other to finish first, causing program stagnation. Generally, program deadlock occurs when the program is running.

Here is a simple example to illustrate the concept

 1 class Zhangsan{ // Define three categories 
 2     public void say(){ 
 3         System.out.println("Zhang San said to Li Si, "if you draw for me, I will give you the book."") ; 
 4     } 
 5     public void get(){ 
 6         System.out.println("Zhang San got the picture.") ; 
 7     } 
 8 }; 
 9 class Lisi{ // Defining four categories of Li 
10     public void say(){ 
11         System.out.println("Li Si said to Zhang San, "if you give me the book, I will give you the picture."") ; 
12     } 
13     public void get(){ 
14         System.out.println("Li Si got the book.") ; 
15     } 
16 }; 
17 public class ThreadDeadLock implements Runnable{ 
18     private static Zhangsan zs = new Zhangsan() ;       // instantiation static Type object 
19     private static Lisi ls = new Lisi() ;       // instantiation static Type object 
20     private boolean flag = false ;  // Declaration flag, judge the first to speak 
21     public void run(){  // Overwrite run()Method 
22         if(flag){ 
23             synchronized(zs){   // Synchronous Zhang San 
24                 zs.say() ; 
25                 try{ 
26                     Thread.sleep(500) ; 
27                 }catch(InterruptedException e){ 
28                     e.printStackTrace() ; 
29                 } 
30                 synchronized(ls){ 
31                     zs.get() ; 
32                 } 
33             } 
34         }else{ 
35             synchronized(ls){ 
36                 ls.say() ; 
37                 try{ 
38                     Thread.sleep(500) ; 
39                 }catch(InterruptedException e){ 
40                     e.printStackTrace() ; 
41                 } 
42                 synchronized(zs){ 
43                     ls.get() ; 
44                 } 
45             } 
46         } 
47     } 
48     public static void main(String args[]){ 
49         ThreadDeadLock t1 = new ThreadDeadLock() ;      // Control Zhang San 
50         ThreadDeadLock t2 = new ThreadDeadLock() ;      // Control Li Si 
51         t1.flag = true ; 
52         t2.flag = false ; 
53         Thread thA = new Thread(t1) ; 
54         Thread thB = new Thread(t2) ; 
55         thA.start() ; 
56         thB.start() ; 
57     } 
58 };

Program running results:


The following code is no longer executed, and the program enters a deadlock state.

summary

So far, some basic operations of multithreading have been introduced. In view of the limited experience of the author, if there are any deficiencies and omissions, welcome to exchange and learn from each other. Thank you!

From: https://blog.csdn.net/lijizhi19950123/article/details/78024612

Topics: Java Attribute jvm