Today is just a carnival for you ----- JAVA thread summary (Introduction to zero Foundation)

Posted by yendor on Sat, 23 Oct 2021 17:37:33 +0200

😎 preface

Today - 1024, the national programmer's Carnival, the blogger once set up a vote to see that everyone is more interested in the blogger's column. According to the results, it is found that JAVA is the most popular, so the author presents this long article as agreed to take a good look at the threaded world in JAVA. The author is Xiaobai. If there are any deficiencies in the article, please don't hesitate to give advice. If you think it's good, one key three links is the greatest affirmation to the author. 😁😁😁

🧐 1, What is a thread?

You're dating. Your girlfriend asks you what's the thread in JAVA? You can answer this:
There are many things going on in our world at the same time. For example, when your little dog is breathing, he can also think, such as what to eat today. The same is true for us. For example, when you are sleeping, of course, in addition to breathing, your heart is beating. In the JAVA world, these simultaneous things are called concurrency, and every thing completed concurrently is called thread.

In the world of programming, not all programming languages can support our threads. Generally, after one task is completed, we can proceed to the next task, and the premise is to wait for the end of our previous task. Our JAVA provides us with a concurrency mechanism. We can execute multiple threads, and each thread can handle a function. This mechanism is multithreading.

Baidu Encyclopedia defines thread as follows:

Thread (English: thread) is the smallest unit that the operating system can schedule operations. It is included in the process and is the actual operation unit in the process. A thread refers to a single sequential control flow in a process. Multiple threads can be concurrent in a process, and each thread executes different tasks in parallel.

emmm. . . You may ask, what is a process?

The so-called process is the execution process of a program in the operating system. More generally speaking, a process is a program with certain independent functions. It is a running activity about a data set in the operating system. It is the basic unit of dynamic execution of operating system programs. In the traditional operating system, process is not only the basic allocation unit of the operating system, but also the basic execution unit of the operating system.

Generally speaking, a thread refers to a single sequential control flow in a process. Multiple threads can be concurrent in a process, and each thread executes different tasks in parallel.

πŸ€” 2, How to implement threads?

❀️❀️ 1. Inherit java.lang.Thread class ❀️❀️

First, Thread is a class in the java.lang package. If you instantiate an object in this package, the instantiated object is called a Thread. We need to create a Thread instance every time we start a new Thread. So how to construct it?
The rookie tutorial says:

The way to create a Thread is to create a new class, which inherits the Thread class, and then create an instance of the class. The inherited class must override the run() method, which is the entry point for the new Thread. It must also call the start() method to execute.

To put it bluntly, it is the following code:

public class ThreadTest extends Thread{
	//Inherit the syntax of the Thread class to create a new Thread
}

The code to realize the real function of our Thread is placed in the run() method of the class. If a class inherits the Thread class, we can override the run() method in the class, write the method to implement this Thread into run(), and then call the start() method in the Thread class to execute the Thread. In essence, we call the run() method.

The Thread object needs a task to execute. The task refers to the work executed by the Thread when it is started. The function code of the work is written in the run() method. Our run() method needs to use the following format:

public void run(){

}

When we execute a threaded program, a thread is automatically generated. Our main method is carried out on this thread. When no other threads are started, this thread is called a single threaded program. The JAVA virtual machine is responsible for the thread startup of our main method. We are only responsible for our own threads.

For example, the following code:

public static void main(String[] args){
	new ThreadTest().start();
}

The rookie tutorial gives us many examples:


Let's look at a chestnut:

public class ThreadTest extends Thread { // The specified class inherits the Thread class
	private int count = 10;
	
	public void run() { // Override the run() method
		while (true) {
			System.out.print(count+" "); // Print count variable
			if (--count == 0) { // Make the count variable self decrement. When the self decrement is 0, exit the loop
				return;
			}
		}
	}
	
	public static void main(String[] args) {
		new ThreadTest().start();
	}
}

Our ThreadTest inherits the Thread class, and then overrides the run() method in this class. This example uses the count - Method to jump out of the loop, thus avoiding the form of infinite loop in the run() method. In our main method, to make the Thread execute, we need to call the start() method in the Thread class. Our start() method calls the overridden run() method. If we don't call the start() method, the Thread will never start. Before the main method does not call the start() method, the Thread method object is just an instance, but it can't be counted as a real Thread.

🀞🀞 2. Implement the java.lang.Runnable interface 🀞🀞

Through the above understanding, we know that threads are mostly created by Thread class. What if we want to inherit other classes? We can use the Runnable interface to implement it.
Let's look at the syntax:

public class Thread extends Object implements Runnable

In fact, by consulting the API documents, we can find that the Thread class implements the Runnable interface, and the run() method is the specific implementation of the run method in the Runnable interface.
The rookie tutorial says:

After creating a class that implements the Runnable interface, you can instantiate a thread object in the class.

There are two constructors in the Thread class:

public Thread(Runnable target)
public Thread(Runnable target,String name)

Here, target is an instance of a class that implements the Runnable interface, and name specifies the name of the new thread. After the new thread is created, you call its start() method before it runs.

The rookie tutorial gives the following examples:

class RunnableDemo implements Runnable {
   private Thread t;
   private String threadName;
   
   RunnableDemo( String name) {
      threadName = name;
      System.out.println("Creating " +  threadName );
   }
   
   public void run() {
      System.out.println("Running " +  threadName );
      try {
         for(int i = 4; i > 0; i--) {
            System.out.println("Thread: " + threadName + ", " + i);
            // Let the thread sleep for a while
            Thread.sleep(50);
         }
      }catch (InterruptedException e) {
         System.out.println("Thread " +  threadName + " interrupted.");
      }
      System.out.println("Thread " +  threadName + " exiting.");
   }
   
   public void start () {
      System.out.println("Starting " +  threadName );
      if (t == null) {
         t = new Thread (this, threadName);
         t.start ();
      }
   }
}
 
public class TestThread {
 
   public static void main(String args[]) {
      RunnableDemo R1 = new RunnableDemo( "Thread-1");
      R1.start();
      
      RunnableDemo R2 = new RunnableDemo( "Thread-2");
      R2.start();
   }   
}

Output results:

Creating Thread-1
Starting Thread-1
Creating Thread-2
Starting Thread-2
Running Thread-1
Thread: Thread-1, 4
Running Thread-2
Thread: Thread-2, 4
Thread: Thread-1, 3
Thread: Thread-2, 3
Thread: Thread-1, 2
Thread: Thread-2, 2
Thread: Thread-1, 1
Thread: Thread-2, 1
Thread Thread-1 exiting.
Thread Thread-2 exiting.

πŸ₯° 3, Thread life cycle

Threads have seven life states: birth, ready, running, waiting, hibernation, blocking and death.
It is written in the introduction to JAVA (Fifth Edition):

The birth state is the state in which the Thread is created. Before the user uses the Thread instance to call the start() method, the Thread is in the birth state. After the user calls the start() method, the Thread is in the ready state. When the Thread gets the system resources, it becomes the running state. Once our Thread enters the executable state, it will transition between ready and running state, and may also enter the state of waiting, hibernation, blocking or death. When a Thread in the running state calls the wait() method in the Thread class, the Thread enters the waiting state. The Thread in the waiting state must call the notify() method of the Thread class before it can be awakened. Our notifyAll() method wakes up all threads in the waiting state. When a Thread calls the sleep() method in the Thread class, it goes into sleep. If a Thread sends an input / output request in the running state, the Thread will enter the blocking state. When it waits for the end of input and output, it will enter the ready state. For the blocked Thread, even if the system resources are idle, the Thread cannot return to the running state. When the Thread's run() method is executed, the Thread enters the dead state.

πŸ€—πŸ€— 1. Thread hibernation πŸ€—πŸ€—

You're dating and your girlfriend is sleepy, so you need to rest. In the JAVA thread world, using the sleep() method, you can use a parameter to specify the sleep time of the thread. The time here is in milliseconds. Generally speaking, our sleep() method is usually put into the run() method, such as the following example, This code will prevent the thread from entering the ready state within 2s:

try{
	Thread.sleep(2000);
}catch(InterruptedException e){
	e.printStackTrace();
}
//printStackTrace() method: print the location and cause of the error in the program

Let's look at another Chestnut:

public class Main {
    public static void main(String[] args) {
        TestSleep();
    }

    public static void TestSleep(){
        int num = 5;
        while (num>=0){
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(num--);
        }
    }
}

You can run by yourself, and you will find that the running box produces a result every second:

🀣🀣 2. Adding threads 🀣🀣

You're on A date, and then your takeout arrives. At this time, you need to get the takeout first, and then go on A date. In fact, in the Thread world, for example, you have A multithreaded program. If you have A Thread A, now you need to insert Thread B into it. At this time, we can use the join() method in Thread. When A Thread uses the join() method to join another Thread, the other Thread will wait for the Thread to execute, Then execute.

We can look at a chestnut before adding another thread:

public class Main {
  public static void main(String[] args) {
    Thread t1 = new Thread(Main::print);
    t1.start();
    System.out.println("Done.");
  }

  public static void print() {
    for (int i = 1; i <= 5; i++) {
      try {
        System.out.println("Counter: " + i);
        Thread.sleep(1000);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
  }
}
Double colons are JDK8 The use of static methods in classes

Operation results:

After adding another thread:

public class Main {
    public static void main(String[] args) {
        Thread t1;
        t1 = new Thread(Main::print);
        t1.start();
        try {
            t1.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Done.");
    }

    public static void print() {
        for (int i = 1; i <= 5; i++) {
            try {
                System.out.println("Counter: " + i);
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
//Double colon is a new feature of JDK8, which is the use of static methods in classes

The result of running is:

When we add the join() method, the original done can only be printed after the added thread ends.

🀨🀨 3. Thread interrupt 🀨🀨

You're on a date. Your girlfriend's takeout arrived. She went to get the takeout. Your date was interrupted. In fact, interruption is to stop our thread. There are three common ways to interrupt threads in JAVA:

public void interrupt()
//Indicates to interrupt the current thread. Only set the interrupt flag bit of the thread.
public static boolean interrupted()
//It returns whether the interrupt bit of the current thread is marked
public boolean isInterrupted()
//The interrupt flag bit is not cleared whether the current thread is interrupted or not.

Let's look at a code. We only need to pay attention to the red part. This code is that a thread uses the interrupted() method and throws an InterruptedException exception to us. When handling the exception, the while loop ends. Because the interrupted() method is called, the corresponding InterruptedException exception is thrown. The rest of the code creates the InterruptedSwing class, implements the Runnable interface, creates a progress bar, and then uses the interrupted() method in the thread representing the progress bar:

Then let's look at the results of the run:

πŸ₯³ 4, Thread priority

You are on a date. Your girlfriend asks you to buy drinks. You should listen to your girlfriend, buy them obediently, and you'd better bring some other small gifts back when you come back. In the Java world, when many of our threads are in the ready state, the system will decide which thread to put into the running state according to the priority. For example, the garbage collection mechanism in Java generally has a low priority. Each newly generated thread inherits the priority of the parent thread.

In our multitasking operating system, each thread will get a small CPU to run. When this small CPU time period belongs to them ends, it will change to another thread to enter the running state.

Our Thread priority can be adjusted by using the setPriority() method. If the priority of this method is not within 1 ~ 10, an exception of IllegalArgumentException will be generated. Here, it should be mentioned that the member variables included in the Thread class represent some priority of the Thread, such as Thread.min_ Priority (constant 1), Thread.max_ Priority (constant 10), Thread.norm_ Priority (constant 5). The priority of each Thread is in Thread.min_ Priority (constant 1) and Thread.max_ Priority (constant 10).

Let's look at a code:

import java.awt.*;
import javax.swing.*;

public class PriorityTest extends JFrame {
	private static final long serialVersionUID = 1L;
	private Thread threadA;
	private Thread threadB;
	private Thread threadC;
	private Thread threadD;
	
	public PriorityTest() {
		getContentPane().setLayout(new GridLayout(4, 1));
		// Instantiate 4 threads respectively
		final JProgressBar progressBar = new JProgressBar();
		final JProgressBar progressBar2 = new JProgressBar();
		final JProgressBar progressBar3 = new JProgressBar();
		final JProgressBar progressBar4 = new JProgressBar();
		getContentPane().add(progressBar);
		getContentPane().add(progressBar2);
		getContentPane().add(progressBar3);
		getContentPane().add(progressBar4);
		progressBar.setStringPainted(true);
		progressBar2.setStringPainted(true);
		progressBar3.setStringPainted(true);
		progressBar4.setStringPainted(true);
		threadA = new Thread(new MyThread(progressBar));
		threadB = new Thread(new MyThread(progressBar2));
		threadC = new Thread(new MyThread(progressBar3));
		threadD = new Thread(new MyThread(progressBar4));
		setPriority("threadA", 5, threadA);
		setPriority("threadB", 5, threadB);
		setPriority("threadC", 4, threadC);
		setPriority("threadD", 3, threadD);
	}
	
	// Defines how to set the name and priority of a thread
	public static void setPriority(String threadName, int priority,
			Thread t) {
		t.setPriority(priority); // Set thread priority
		t.setName(threadName); // Sets the name of the thread
		t.start(); // Start thread
	}
	
	public static void main(String[] args) {
		init(new PriorityTest(), 100, 100);
	}
	
	public static void init(JFrame frame, int width, int height) {
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setSize(width, height);
		frame.setVisible(true);
	}
	
	private final class MyThread implements Runnable { // Define a class that implements the Runnable interface
		private final JProgressBar bar;
		int count = 0;
		
		private MyThread(JProgressBar bar) {
			this.bar = bar;
		}
		
		public void run() { // Override the run() method
			while (true) {
				bar.setValue(count += 10); // Set the value of the scroll bar to increase by 10 each time
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					System.out.println("The current line program is interrupted");
				}
			}
		}
	}
	
}

Operation results (in fact, the first progress bar is changed first, and the priorities of C and D are later, which may be difficult to identify with the naked eye):

We can better understand it through a picture:

Thread A with priority 5 gets the CPU first, and then B gets the opportunity to execute. When B finishes executing, it continues to execute A, and it will not rotate to C until both A and B finish executing. When C finishes executing, it will rotate to D to continue executing.

πŸ₯΄ 5, Thread synchronization

You are dating. You play with your partner. You and your partner should play or talk at the same time. It is impossible to turn you into a robot and act only after receiving instructions. In the world of JAVA, a single threaded program can only do one thing at a time, but the latter can only continue to execute after the previous thing is completed. If we use multithreading, two threads may seize the same resource at the same time. Our JAVA provides a thread synchronization mechanism to prevent access conflicts between resources.

πŸ‘ΎπŸ‘Ύ 1. Thread safety πŸ‘ΎπŸ‘Ύ

You are dating and your girlfriend wants to go to the cinema, but there is only one ticket left for that show. If our cinema does not consider what to do if the tickets are sold out when designing the ticket system, the following situation may occur:

public class Main implements Runnable {
    int num = 10; // Set the current total number of votes

    public void run() {
        while (true) {
            if (num > 0) {
                try {
                    Thread.sleep(1000);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                System.out.println("tickets" + num--);
            }
        }
    }

    public static void main(String[] args) {
        Main t = new Main(); // Instantiate class object
        Thread tA = new Thread(t); // Instantiate 4 threads with this kind of object
        Thread tB = new Thread(t);
        Thread tC = new Thread(t);
        Thread tD = new Thread(t);
        tA.start(); // Start threads separately
        tB.start();
        tC.start();
        tD.start();
    }
}

Operation results:

This is because this program creates four threads at the same time. These four threads execute the run() method. When there is only one ticket left, that is, when num is 1, threads 1, 2, 3 and 4 have the function of storing num variables. When our thread 1 finishes executing the run() method, we specify that it enters sleep() before we have time to perform the decrement operation The method of thread 1 has entered the ready state, but threads 2, 3 and 4 have entered the run() method. At this time, they feel that the value of num is still greater than 0, but in fact, thread 1 has not awakened and is still in the sleep state. When the sleep state of thread 1 ends, Num changes to 0, but the other threads also perform the minus one operation, so a negative value is generated.

πŸ€–πŸ€– 2. Thread synchronization πŸ€–πŸ€–

You're on a date. You want to go for convenience, but you find that there is someone in the only position in the toilet. You should wait for the guy to come out and you can go in again. For multi-threaded access to shared resources, in order to avoid access conflict, we can add a lock, just like the door of the toilet. This can solve the problem of resource sharing.

The synchronization mechanism in JAVA can effectively solve problems. Using the keyword synchronized, let's look at a program:

public class Main implements Runnable {
    int num = 10;

    public void run() {
        while (true) {
            synchronized ("") {
                if (num > 0) {
                    try {
                        Thread.sleep(1000);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    System.out.println("tickets" + --num);
                }
            }
        }
    }

    public static void main(String[] args) {
        Main t = new Main();
        Thread tA = new Thread(t);
        Thread tB = new Thread(t);
        Thread tC = new Thread(t);
        Thread tD = new Thread(t);
        tA.start();
        tB.start();
        tC.start();
        tD.start();
    }
}

Operation results:

Syntax of synchronized:

synchronized(Object){
}

Generally, the operation of shared resources is placed in the synchronized defined area. If other threads want to access it, they must wait for the lock to be released before entering the area.

In introduction to JAVA (Fifth Edition), Object is described as follows:
Object is any object. Each object has a flag bit and has two values, 0 and 1. When a thread runs to the synchronization block, it first checks the flag bit of the object. If the flag bit is 0, it indicates that other threads are running in the synchronization block. At this time, the thread is ready until the thread in the synchronization block executes the code in the synchronization block. At this time, the flag bit of the object is set to 1, the thread can execute the code in the synchronization block, and set the flag bit of the object to 0 to prevent other threads from executing the code in the synchronization block.

Synchronization method:

//Syntax:
synchronized void f(){
}

Let's change the above code:

class Sell implements Runnable {
    int num = 10;
    public void run() {
        while (true) {
            if (num > 0)
                sell();
        }
    }

    public synchronized void sell() {
        if (num> 0) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("tickets" + --num);
        }
    }
}

public class Main {
    public static void main(String args[]) {
        Sell t = new Sell();
        Thread tA = new Thread(t); // Instantiate 4 threads with this kind of object
        Thread tB = new Thread(t);
        Thread tC = new Thread(t);
        Thread tD = new Thread(t);
        tA.start(); // Start threads separately
        tB.start();
        tC.start();
        tD.start();
    }
}

The running result is the same as that using the synchronization block:

The code in this article is rewritten from "Introduction to JAVA (Fifth Edition)"
For some knowledge analysis, please refer to the blog:
https://www.cnblogs.com/yangming1996/p/9647047.html

https://www.cnblogs.com/three-fighter/p/14396208.html

https://www.cnblogs.com/tietazhan/p/7486937.html?tdsourcetag=s_pctim_aiomsg

https://www.runoob.com/java/java-multithreading.html

πŸ₯³πŸ₯³πŸ₯³ This article has been written continuously for nearly a week. Although we have different views on the hot list recently, it seems that the hot list is resisting long articles of more than 10000 words. But I still intend to publish this 10000 word long article today, because I believe many people still don't want to see a few lines of code on the hot list, so many bloggers will express such feelings: "I hope there are some likes, collections or messages under my article, even if I can't get on the hot list, but I don't like the situation of 0 likes 0 collections 1 reading the hot list." 🀞🀞🀞
If there are any mistakes in the article, you are welcome to leave a message in the comment area. The author is shallow in talent and learning. I hope you masters will not hesitate to give me advice.

Topics: Java Multithreading