The most comprehensive analysis of Java multithreading usage. If you have not conducted in-depth research on Java's multithreading mechanism, then this article can help you more thoroughly understand the principles and usage methods of Java multithreading.
1. Create a thread
There are two ways to create threads in Java: using the Thread class and using the Runnable interface. When using the Runnable interface, you need to create a Thread instance. Therefore, whether you are establishing a thread through the Thread class or the Runnable interface, you must establish an instance of the Thread class or its subclass. Thread constructor:
Method 1: Inherit the Thread class and overwrite the run method
public class ThreadDemo1 { public static void main(String[] args){ Demo d = new Demo(); d.start(); for(int i=0;i<60;i++){ System.out.println(Thread.currentThread().getName()+i); } } } class Demo extends Thread{ public void run(){ for(int i=0;i<60;i++){ System.out.println(Thread.currentThread().getName()+i); } } }Method 2:
public class ThreadDemo2 { public static void main(String[] args){ Demo2 d =new Demo2(); Thread t = new Thread(d); t.start(); for(int x=0;x<60;x++){ System.out.println(Thread.currentThread().getName()+x); } }}class Demo2 implements Runnable{ public void run(){ for(int x=0;x<60;x++){ System.out.println(Thread.currentThread().getName()+x); } }}2. The life cycle of threads
Just like people have birth, old age, sickness and death, threads also have to go through four different states: start (wait), run, suspend and stop. All four states can be controlled by methods in the Thread class. The following is a method related to these four states in the Thread class.
// Start thread
publicvoid start( );
publicvoid run( );
// Suspend and wake up threads
publicvoid resume( ); // Not recommended to use
publicvoid suspend( ); // Not recommended to use
publicstaticvoid sleep(long millis);
publicstaticvoid sleep(long millis, int nanos);
// Terminate the thread
Publicvoid stop( ); // Not recommended to use
publicvoid interrupt( );
// Get the thread state
publicboolean isAlive( );
publicboolean isInterrupted( );
publicstaticboolean interrupted( );
// Join method
publicvoid join( ) throws InterruptedException;
After the thread is established, it does not execute the code in the run method immediately, but is in a waiting state. When the thread is in a waiting state, you can use the Thread class method to set various properties of the thread, such as the thread's priority (setPriority), thread name (setName) and thread type (setDaemon), etc.
After calling the start method, the thread starts executing the code in the run method. The thread enters the running state. You can use the isAlive method of the Thread class to determine whether the thread is in running state. When the thread is in the running state, isAlive returns true. When isAlive returns false, the thread may be in the waiting state or in the stop state. The following code demonstrates the switching between the three states of creating, running and stopping of threads, and outputs the corresponding isAlive return value.
Once the thread starts executing the run method, the thread will not exit until the run method is executed. However, during the execution of a thread, the thread can be temporarily stopped by two methods. These two methods are suspend and sleep. After suspending the thread with suspend, the thread can be awakened through the resume method. After using sleep to sleep, the thread can only be put in the ready state after the set time (after the thread sleeps, the thread may not execute immediately, but it just enters the ready state and waits for the system to schedule).
There are two things to note when using the sleep method:
1. The sleep method has two overload forms. One of the overload forms can not only be set to milliseconds, but also nanoseconds (1,000,000 nanoseconds equals 1 millisecond). However, Java virtual machines on most operating system platforms cannot be accurate to nanoseconds, so if nanoseconds are set for sleep, the Java virtual machine will take the milliseconds closest to this value.
2. When using the sleep method, you must use throws or try{…}catch{…}. Because the run method cannot use throws, you can only use try{…}catch{…}. When the thread is sleeping, sleep will throw an InterruptedException exception when interrupting the thread using the interrupt method. The sleep method is defined as follows:
publicstaticvoid sleep(long millis) throws InterruptedException
publicstaticvoid sleep(long millis, int nanos) throws InterruptedException
There are three ways to terminate the thread.
1. Use the exit flag to make the thread exit normally, that is, the thread terminates when the run method is completed.
2. Use the stop method to forcefully terminate the thread (this method is not recommended because stop is the same as suspend and resume, and may also have unpredictable results).
3. Use the interrupt method to interrupt the thread.
1. Use the exit flag to terminate the thread
When the run method is executed, the thread will exit. But sometimes the run method never ends. For example, using threads to listen to client requests in server programs, or other tasks that require loop processing. In this case, these tasks are usually placed in a loop, such as while loop. If you want the loop to run forever, you can use while(true){…} to handle it. However, if you want to make the while loop exit under a certain condition, the most direct way is to set a boolean type flag and control whether the while loop exits by setting this flag to true or false. Here is an example of terminating a thread using the exit flag.
The function of the join method is to turn the asynchronous execution thread into synchronous execution. That is to say, when the start method of the thread instance is called, the method will return immediately. If a value calculated by this thread needs to be used after the start method is called, the join method must be used. If you do not use the join method, it cannot be guaranteed that when a statement behind the start method is executed, the thread will be executed. After using the join method, the program will not be executed until the thread exits. The following code demonstrates the usage of join.
3. Multithreaded safety issues
Cause of the problem: When multiple statements are operating on the same thread to share data, one thread only executes part of multiple statements, but has not finished executing it yet, and another thread participates in the execution, resulting in an error in sharing data.
Solution: For multiple statements that share data with multiple operations, only one thread can be executed. During the execution process, other threads do not execute.
Synchronize code blocks:
public class ThreadDemo3 { public static void main(String[] args){ Ticket t = new Ticket(); Thread t1 = new Thread(t,"Window One"); Thread t2 = new Thread(t,"Window Two"); Thread t3 = new Thread(t,"Window Three"); Thread t4 = new Thread(t,"Window Four"); t1.start(); t2.start(); t3.start(); t4.start(); }}class Ticket implements Runnable{ private int ticket =400; public void run(){ while(true){ synchronized (new Object()) { try { Thread.sleep(1); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } if(ticket<=0) break; System.out.println(Thread.currentThread().getName()+"---sell"+ticket--); } } }}Synchronous functions
public class ThreadDemo3 { public static void main(String[] args){ Ticket t = new Ticket(); Thread t1 = new Thread(t,"Window One"); Thread t2 = new Thread(t,"Window Two"); Thread t3 = new Thread(t,"Window Three"); Thread t4 = new Thread(t,"Window Four"); t1.start(); t2.start(); t3.start(); t4.start(); }}class Ticket implements Runnable{ private int ticket = 4000; public synchronized void saleTicket(){ if(ticket>0) System.out.println(Thread.currentThread().getName()+"selled"+ticket--); } public void run(){ while(true){ saleTicket(); } }}Synchronous function lock is this static synchronization function lock is class
Communication between threads
public class ThreadDemo3 { public static void main(String[] args){ class Person{ public String name; private String gender; public void set(String name,String gender){ this.name =name; this.gender =gender; } public void get(){ System.out.println(this.name+"...."+this.gender); } } final Person p =new Person(); new Thread(new Runnable(){ public void run(){ int x=0; while(true){ if(x==0){ p.set("Zhang San", "male"); }else{ p.set("lili", "nv"); } x=(x+1)%2; } } }).start(); new Thread(new Runnable(){ public void run(){ while(true){ p.get(); } } }).start(); }}/*Zhang San....Male Zhang San....Male lili....nvlili....Male Zhang San....nvlili....Male */Modify the above code
public class ThreadDemo3 { public static void main(String[] args){ class Person{ public String name; private String gender; public void set(String name,String gender){ this.name =name; this.gender =gender; } public void get(){ System.out.println(this.name+"...."+this.gender); } } final Person p =new Person(); new Thread(new Runnable(){ public void run(){ int x=0; while(true){ synchronized (p) { if(x==0){ p.set("Zhang San", "male"); }else{ p.set("lili", "nv"); } x=(x+1)%2; } } } } }).start(); new Thread(new Runnable(){ public void run(){ while(true){ synchronized (p) { p.get(); } } } } }).start(); } } /* lili....nv lili....nv lili....nv lili....nv lili....nv lili....nv lili....nv lili....nv lili....nv lili....nv Zhang San....male Zhang San....male Zhang San....male Zhang San....male Zhang San....male Zhang San....male Zhang San....male Zhang San....male Zhang San....male Zhang San....male */Waiting for wake-up mechanism
/* *Thread waiting wake-up mechanism*Wait and wake-up must be the same lock*/public class ThreadDemo3 { private static boolean flags =false; public static void main(String[] args){ class Person{ public String name; private String gender; public void set(String name,String gender){ this.name =name; this.gender =gender; } public void get(){ System.out.println(this.name+"...."+this.gender); } } final Person p =new Person(); new Thread(new Runnable(){ public void run(){ int x=0; while(true){ synchronized (p) { if(flags) try { p.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); }; if(x==0){ p.set("Zhang San", "Male"); }else{ p.set("lili", "nv"); } x=(x+1)%2; flags =true; p.notifyAll(); } } } } }).start(); new Thread(new Runnable(){ public void run(){ while(true){ synchronized (p) { if(!flags) try { p.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); }; p.get(); flags =false; p.notifyAll(); } } } } }).start(); }}Production and consumption mechanism one
public class ThreadDemo4 { private static boolean flags =false; public static void main(String[] args){ class Goods{ private String name; private int num; public synchronized void produce(String name){ if(flags) try { wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } this.name =name+"number: "+num++; System.out.println("Produced......"+this.name); flags =true; notifyAll(); } public synchronized void consumption(){ if(!flags) try { wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("Consumed*****"+name); flags =false; notifyAll(); } } final Goods g =new Goods(); new Thread(new Runnable(){ public void run(){ while(true){ g.produce("product"); } } }).start(); new Thread(new Runnable(){ public void run(){ while(true){ g.consume(); } } }).start(); }}Production and consumption mechanism 2
public class ThreadDemo4 { private static boolean flags =false; public static void main(String[] args){ class Goods{ private String name; private int num; public synchronized void produce(String name){ while(flags) try { wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } this.name =name+"number: "+num++; System.out.println(Thread.currentThread().getName()+"produced..."+this.name); flags =true; notifyAll(); } public synchronized void consume(){ while(!flags) try { wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"consumed*******"+name); flags =false; notifyAll(); } } final Goods g =new Goods(); new Thread(new Runnable(){ public void run(){ while(true){ g.produce("product"); } } },"Produce("product"); } } },"Produce("product"); } } },"Produce("product"); } } },"Produce("product"); } } },"Produce("product"); } } },"Consumer No. 1").start(); new Thread(new Runnable(){ public void run(){ while(true){ g.consume(); } } },"Consumer No. 2").start(); }}/*Consumer No. 2 consumed*******Commodity number: 48049Producer No. 1 produced......Commodity number: 48050Consumer No. 1 consumed*******Commodity number: 48050Producer No. 1 produced...Commodity number: 48051Consumer No. 2 consumed****Commodity number: 48051Producer No. 2 produced...Commodity number: 48052Consumer No. 2 consumed*** ***Commodity number: 48052Producer No. 1 has been produced......Commodity number: 48053Consumer No. 1 has been consumed*******Commodity number: 48053Producer No. 1 has been produced...Commodity number: 48054Consumer No. 2 has been consumed*******Commodity number: 48054Producer No. 2 has been produced...Commodity number: 48055Consumer No. 2 has been consumed*******Commodity number: 48055*/The above is the compilation of Java multi-threaded information. We will continue to add relevant knowledge in the future. Thank you for your support for this site!