One , summary
stay JAVA in , use Thread Class represents a thread , All thread objects , All have to be Thread Class or Thread An instance of a subclass of a class . The task of each thread is to execute a sequence of code
,JAVA Use the thread executable to hold the code . therefore , When we create a thread , Mainly according to the actual demand , Write the code to put into the thread execution body .
Two , Three creation methods
2.1 The first one , By inheritance Thread Class creates a thread class
By inheritance Thread Class to create and start multithreading :
1, Define a class inheritance Thread class , And rewrite Thread Class run() method ,run() The method body of a method is the task to be completed by the thread , So the run() The execution body called a thread ;
2, Create an instance object of the class , The thread object is created ;
3, Calling the thread object's start() Method to start the thread ;
Code instance :
public class ExtendThread extends Thread { private int i; public static void
main(String[] args) { for(int j = 0;j < 50;j++) {
// call Thread Class currentThread() Method to get the current thread
System.out.println(Thread.currentThread().getName() + " " + j); if(j == 10) {
// Create and start the first thread new ExtendThread().start(); // Create and start a second thread new
ExtendThread().start(); } } } public void run() { for(;i < 100;i++) {
// By inheritance Thread Class to implement multithreading , It can be used directly this Gets the currently executing thread System.out.println(this.getName() +
" " + i); } } }
Code dependent :
1, Above getName() Method is to return the name of the current thread , It can also be done through setName() Method to set the name of the current thread ;
2, When JAVA After running the program , The program creates at least one main thread ( automatic ), The thread execution body of the main thread is not run() Method determined , Instead, it was created by main() Method determined ;
3, By default , The thread name of the main thread is main, The threads created by the user are Thread—1,Thread—2,....Thread—3;
code analysis :
This is a screenshot of the code running , As can be seen from the figure :
1, There are three threads :main,Thread-0 ,Thread-1
2,Thread-0 ,Thread-1 Member variables output by two threads i The value of is discontinuous ( there i It's an instance variable, not a local variable
). because : By inheritance Thread Class implements multithreading , Each thread is created with a different subclass object , cause Thread-0 ,Thread-1 Two threads cannot share member variables i ;
3, Thread execution is preemptive , It didn't say Thread-0 perhaps Thread-1 Always occupied CPU( This is also related to thread priority , here Thread-0
,Thread-1 Same thread priority , The knowledge about thread priority is not expanded here );
2.2 The second kind , By implementing Runnable Interface to create thread class
The steps to create and start multithreading in this way are as follows :
1, Define a class implementation Runnable Interface ;
2, Create an instance object of the class obj;
3, take obj Pass in as a constructor parameter Thread Class instance object , This object is the real thread object ;
4, Calling the thread object's start() Method to start the thread ;
Code instance :
public class ImpRunnable implements Runnable { private int i; @Override public
void run() { for(;i < 50;i++) {
// When the thread class is implemented Runnable Interface time , To get the current thread object, you must pass the Thread.currentThread() obtain
System.out.println(Thread.currentThread().getName() + " " + i); } } public
static void main(String[] args) { for(int j = 0;j < 30;j++) {
System.out.println(Thread.currentThread().getName() + " " + j); if(j == 10) {
ImpRunnable thread_target = new ImpRunnable(); // adopt new
Thread(target,name) To create a thread new Thread(thread_target," thread 1").start(); new
Thread(thread_target," thread 2").start(); } } } }
Code dependent :
1, realization Runnable The instance object of the class of the interface is only used as Thread Object's target,Runnable Implement the run() Methods are only used as thread executors , and
The actual thread object is still Thread example , there Thread Instance is responsible for executing its target Of run() method ;
2, By implementing Runnable Interface to implement multithreading , To get the current thread object, you can only use Thread.currentThread() method , And can't pass this Keyword acquisition ;
3, from JAVA8 start ,Runnable The interface uses the @FunctionlInterface modification , in other words Runnable Interface is a functional interface , Can make
use lambda Expression create object , use lambda Expressions can be created without creating an implementation like the above code Runnable The class of the interface , Then create an instance of the class .
code analysis :
This is a screenshot of the result of running the code , As can be seen from the figure :
1, thread 1 And threads 2 Output member variables i It's continuous , In other words, threads are created in this way , You can make multiple threads share instance variables of the thread class
, Because multiple threads here use the same one target Instance variable . however , When you run with my code above , You'll find out , In fact, some of the results are not continuous , This is because multiple threads access the same resource , If the resource is not locked , Then it will appear
Thread safety ( This is the knowledge of thread synchronization , It doesn't unfold here );
2.3 The third kind , adopt Callable and Future Interface creation thread
Create threads through these two interfaces , You need to know what these two interfaces do , Let's take a look at these two interfaces : By implementing Runnable Interface creates multithreading ,Thread The function of class is to run() Method is wrapped into the execution body of the thread , that , Is it possible to directly
How about wrapping any method as an executable of a thread ? from JAVA5 start ,JAVA Provided by Callable Interface , The interface is Runnable Enhanced version of the interface ,
Callable Interface provides a call() Methods can be used as thread executors , but call() Method comparison run() More powerful methods ,call() The powerful function of the method is embodied in :
1,call() Method can have a return value ;
2,call() Method can declare to throw an exception ;
You can see from this , It can provide one Callable Object as Thread Of target, The thread execution body of the thread is call() method . But the problem is :
Callable The interface is JAVA New interfaces , And it's not Runnable Sub interface of the interface , therefore Callable Object cannot be directly used as Thread Of target
. Another reason is that :call() Method has a return value ,call() Method is not called directly , It is called as the thread execution body , So it's about getting call() Method return value problem .
therefore ,JAVA5 Provided Future Interface Callable In the interface call() The return value of the method , And for Future Interface provides a FutureTask Implementation class , This class
Yes Future Interface , And realized Runnable Interface , therefore FutureTask Can be used as Thread Class target
, It's also solved Callable Object cannot be used as Thread Class target This problem .
stay Future The interface defines the following public methods to control the Callable task :
1,boolean cancel(boolean mayInterruptIfRunning): Attempt to cancel Future Related in Callable task ;
2,V get(): return Callable Mission call() The return value of the method , Calling this method causes the program to block , You must wait until the child thread finishes before you get the return value ;
3,V get(long timeout, TimeUnit
unit): return Callable Mission call() The return value of the method . This method makes the program block at most timeout and unit Specified time , If the specified time has passed ,Callable The task still has no return value , Will be thrown out TimeoutException abnormal ;
4,boolean isCancelled(): If Callable The task was cancelled before it was completed normally , Return to true;
5,boolean isDone(): If Callable The task has been completed , Return to true;
This is how to start the multithreading :
1, establish Callable Interface implementation class , And realize call() method , This method will be used as the thread execution body , And the method has a return value , Recreate Callable An instance of an implementation class ;
2, use FutureTask Class Callable object , The FutureTask Object encapsulates the Callable Object's call() The return value of the method ;
3, use FutureTask Object as Thread Object's target Create and start a new thread ;
4, call FutureTask Object's get() Method to get the return value after the execution of the child thread .
Code instance :
public class ThirdThreadImp { public static void main(String[] args) {
// here call() Method is rewritten using the lambda expression , There is no new one Callable The implementation class of the interface FutureTask<Integer> task = new
FutureTask<Integer>((Callable<Integer>)()->{ int i = 0; for(;i < 50;i++) {
System.out.println(Thread.currentThread().getName() + " The loop variable in the execution body of the thread i The value of is :" +
i); } //call() The return value of the method return i; }); for(int j = 0;j < 50;j++) {
System.out.println(Thread.currentThread().getName() + " Loop variables of Large Cycles j The value of is :" + j);
if(j == 20) { new Thread(task," Threads with return values ").start(); } } try {
System.out.println(" The return value of the child thread :" + task.get()); } catch (Exception e) {
e.printStackTrace(); } } }
Code dependent :
1, The above code does not use to create an implementation Callable The class of the interface , Then create an implementation class instance . because , from JAVA8 It can be used directly at first
Lambda Create an expression Callable object , So the code above uses Lambda expression ;
2,call() Method return value type and creation FutureTask Object time <> In the same type .
code analysis :
There is not much analysis here , Just look at the output of the last line : call FutureTask Object's get() method , You must wait until the child thread finishes , Will have a return value .
Three , Comparison of three creation methods
That's all JAVA Three ways to create threads in , We can know by comparison ,JAVA The implementation of multithreading can be divided into two categories : One is inheritance Thread Class to implement multithreading ; The other is : By implementing Runnable Interface or Callable Interface implementation multithreading .
Let's analyze the advantages and disadvantages of these two kinds of multithreading methods :
By inheritance Thread Class to implement multithreading :
advantage :
1, It's easy to implement , And get the current thread , No call is required Thread.currentThread() method , Direct use this To get the current thread ;
shortcoming :
1, Thread class already inherited Thread Class , You can no longer inherit other classes ;
2, Multiple threads cannot share the same resource ( As in the previous analysis of member variables i );
By implementing Runnable Interface or Callable Interface implementation multithreading :
advantage :
1, The thread class only implements the interface , You can also inherit other classes ;
2, Multiple threads can use the same target object , It is suitable for multiple threads to process the same resource .
shortcoming :
1, In this way, multithreading is realized , Compared with the first type , Programming is complex ;
2, To access the current thread , Must be called Thread.currentThread() method .
All in all :
Generally, the second method is adopted to realize multithreading .
Technology