This article is a summary of the basic usage of Java multithreading.
This article will explain the basic usage of Java multithreading from the following aspects:
How to use multithreading
Two ways to start a thread
Java provides two ways to use multi-threading. One is to write a class to inherit Thread, then overwrite the run method, and then call the start method to start the thread. At this time, this class will run the code in the run method in the way another thread. Another way is to write a class to implement the Runnable interface, then implement the interface method run, and then create a Thread object, use the class that implements the Runnable interface as a construction parameter, pass it into the Thread object, and finally the Thread object calls the start method.
The start method here is a method with startup function, which internally calls back the run method. Therefore, only when the start method is called will another thread be started, the run method will be called directly, or run in the same thread, rather than running in another thread
In addition, the start method just tells the virtual machine that the thread can be started, which means that the thread is in the ready state, but it does not mean that the call to start will run immediately. This requires waiting for the JVM to decide when to execute the thread. In other words, if there are two threads A and B, A calls start first, and B calls start later, it does not mean that thread A runs first, and thread B runs later. This is all determined by the JVM and can be considered random startup.
Below we use actual code to illustrate two ways to start threads:
The first type is inheriting Thread
public class ExampleThread extends Thread{ @Override public void run() { super.run(); System.out.println("This is an ExampleThread inherited from Thread"); }}The test code can be found in the ExampleThreadTest class in the test directory
Another way, implements the Runnable interface
public class ExampleRunable implements Runnable{ public void run() { System.out.println("This is the class that implements the Runnable interface"); }}For the test code, you can see the ExampleRunableTest class in the test directory.
How to get some information about multithreading
After starting multi-threading, we hope to obtain some information about the started thread through some APIs. JDK provides us with a Thread class method to get some information about the thread.
Get the name of the thread
These methods are internal methods of Thread, so we can call these methods in two ways. One is that when our class inherits Thread to use multi-thread, we can use this to call it. Another way is to call these methods through Thread.currentThread() . However, these two methods are different in different usage scenarios.
Let’s briefly look at the use of two methods.
The first Thread.currentThread() is used, the code is as follows:
public class ExampleCurrentThread extends Thread{ public ExampleCurrentThread(){ System.out.println("Print of constructor method: " + Thread.currentThread().getName()); } @Override public void run() { super.run(); System.out.println("Print of run method: " + Thread.currentThread().getName()); }}The test code is as follows:
public class ExampleCurrentThreadTest extends TestCase { public void testInit() throws Exception{ ExampleCurrentThread thread = new ExampleCurrentThread(); } public void testRun() throws Exception { ExampleCurrentThread thread = new ExampleCurrentThread(); thread.start(); Thread.sleep(1000); }}The results are as follows:
Printing of the constructor method: Printing of the mainrun method: Printing of the Thread-0 Construction method: main
Why does we use Thread.currentThread() inside ExampleCurrentThread to display that the construction method is printed as main, because Thread.currentThread() returns the information that the code segment is being called by that thread. It is obvious that the construction method is executed by the main thread, and the run method is executed by the thread we started by ourselves. Because it is not named, it is default Thread-0.
Next, we are taking a look at inheriting from Thread and calling it with this.
public class ComplexCurrentThread extends Thread{ public ComplexCurrentThread() { System.out.println("begin========="); System.out.println("Thread.currentThread().getName=" + Thread.currentThread().getName()); System.out.println("this.getName()=" + this.getName()); System.out.println("end==========="); } @Override public void run() { super.run(); System.out.println("run begin==========="); System.out.println("Thread.currentThread().getName=" + Thread.currentThread().getName()); System.out.println("this.getName()=" + this.getName()); System.out.println("run end=================="); }}The test code is as follows:
public class ComplexCurrentThreadTest extends TestCase { public void testRun() throws Exception { ComplexCurrentThread thread = new ComplexCurrentThread(); thread.setName("byhieg"); thread.start(); Thread.sleep(3000); }}The results are as follows:
begin===========Thread.currentThread().getName=mainthis.getName()=Thread-0end===================== Run begin========Thread.currentThread().getName=byhiegthis.getName()=byhiegrun end===========
First of all, when creating the object, the constructor is still executed by the main thread, so Thread.currentThread() gets the name of the Main thread, but this method refers to the object that calls the method, that is, the thread information of ComplexCurrentThread. There is no setName yet, so it is the default name. Then the run method is either Thread.currentThread() or this returns thread information with the byhieg name set.
So Thread.currentThread refers to the thread information that specifically executes this code block. The constructor is executed by main, and the run method is which thread starts and which thread executes run. From this point of view, the information that this can get is inaccurate, because if we execute this.getName() in run, but the run method is started by another thread, we cannot get the information of the new city running the run method through this.getName. And only classes that inherit Thread can have methods such as getName, which is a disaster for Java's feature languages that do not have multiple inheritances. For all the information about the threads that we want to get afterwards, we use Thread.currentThread() to call the API.
Get the thread's ID
Call getID to get the unique identification of the thread. This is the same as the usage of getName above. There is nothing to say. You can directly look at ExampleIdThread and its test class ExampleIdThreadTest.
Determine whether the thread survives
The function of the method isAlive() is to test whether the thread is active. The so-called active state means that the thread has been started but has not terminated. That is, after the thread starts, it is considered to be alive.
Let's take a look at specific examples:
public class AliveThread extends Thread{ @Override public void run() { super.run(); System.out.println("Is it alive in the run method" + " " + Thread.currentThread().isAlive()); }}The test method is as follows:
public class AliveThreadTest extends TestCase { public void testRun() throws Exception { AliveThread thread = new AliveThread(); System.out.println("begin == " + thread.isAlive()); thread.start(); Thread.sleep(1000); System.out.println("end ==" + thread.isAlive()); Thread.sleep(3000); }}The results are as follows:
begin == Whether trueend in the false method ==false
We can find that before start, the thread is considered to be unsurvived, and then when it runs, it is alive. When the run method is executed, it is considered to be unsurvived.
How to stop a thread
Determine whether the thread has terminated
JDK provides some methods to determine whether the thread is terminated - isInterrupted() and interrupted()
How to stop threads
This is a more important method in obtaining thread information, because it is related to the method of terminating threads. Let me first talk about several ways to terminate threads:
I won’t talk about the first one, the second stop() method has been abandoned because the following reasons may occur:
For specific examples, you can see StopLockThread and its test class StopLockThreadTest
The third type is the currently recommended termination method, calling interrupt, and then determining whether to terminate in the run method. There are two ways to judge the termination. One is the static method interrupted() of the Thread class, and the other is the Thread member method isInterrupted(). There is a difference between these two methods. The first method will automatically reset the state. If interrupted() is called twice in a row, if it is false the first time, the second time it must be true. And isInterrupted() won't.
Examples are as follows:
public class ExampleInterruptThread extends Thread{ @Override public void run() { super.run(); try{ for(int i = 0 ; i < 50000000 ; i++){ if (interrupted()){ System.out.println("It is already a stop state, I want to exit"); throw new InterruptedException("Stop......"); } System.out.println("i=" + (i + 1)); } } catch (InterruptedException e){ System.out.println("Stop smoothly"); } }}The test code is as follows:
public class ExampleInterruptThreadTest extends TestCase { public void testRun() throws Exception { ExampleInterruptThread thread = new ExampleInterruptThread(); thread.start(); Thread.sleep(1000); thread.interrupt(); }}The fourth method is the same as the third one. The only difference is to replace the thrown exception in the above code with return. I still like to throw exceptions. There are many forms of processing here, such as printing information, closing or capturing the resource and then throwing it to the upper layer again.
Note that the exception we threw above is an InterruptedException. Here we briefly talk about the reasons why this exception may be generated. In the case of the original thread sleep, call interrupt to terminate the thread, or terminate the thread first and then let the thread sleep.
How to pause thread
The following two methods are provided in the JDK for pausing threads and restoring threads.
These two methods are abandoned methods like the stop method, and their usage is the same as stop, brutally suspending threads and restoring threads. The main reasons why these two methods are abandoned are:
Some other usages of threads
Some other basic usages of threads are as follows:
Thread concessions
JDK provides the yield() method to make the thread give up the current CPU resource and give it to other tasks to occupy CPU time, but this is also a random thing. It is possible that it will take up the time slice just after giving up the resources.
For specific examples, please refer to ExampleYieldThread and its test class ExampleYieldThreadTest
Set the priority of threads
We can set the priority of threads to let the CPU as much as possible to send the execution resources to threads with higher priority. Java sets 1-10 10 priority levels, and there are three static variables to provide three priority levels:
/** * The minimum priority that a thread can have. */ public final static int MIN_PRIORITY = 1; /** * The default priority that is assigned to a thread. */ public final static int NORM_PRIORITY = 5; /** * The maximum priority that a thread can have. */ public final static int MAX_PRIORITY = 10;
We can set the priority of the thread through setPriority, and can directly pass in three static variables for appeal, or directly pass in numbers 1-10. After setting, the thread will have different priorities. What happens if we don't set priority?
The priority of threads is inherited. If we start thread B in thread A, AB has the same priority. Generally, when we start a thread in the main thread, we have consistent priority with the main thread. The priority of main thread is 5 by default.
Here are some rules for priority:
Thread guard
The JDK provides a setDaemon method to set a thread to become a daemon thread. The characteristic of daemon threads is that after other non-daemon threads are executed, the daemon threads will be automatically destroyed. A typical example is the GC recycler.
For details, you can see ExampleDaemonThread and ExampleDaemonThreadTest.
Summarize
This article mainly summarizes some basic usages of Java threads, and is included in the second article about thread safety and synchronization.
The above is all the content of this article. I hope that the content of this article will be of some help to everyone’s study or work. I also hope to support Wulin.com more!