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!