There are three ways to create threads in Java:
(1) Inheriting Thread mode;
(2) Implementing Runnable interface;
(3) Create through Callable interface and FutureTask class.
Many people know the first two ways of creating, and also know their respective advantages and disadvantages. The latter may be relatively unfamiliar, and the frequency of questions in the interview is relatively high. If you can answer three kinds of questions and introduce the characteristics of each way, it is estimated that it will give the interviewer a better feedback. Following are examples to illustrate the steps and differences of various creation methods.
(1) Inheritance of Thread
Create a subclass of Thread and override the run method of that class. The run method body is the task that the thread needs to complete. The run() method is also called the thread's executor.
(2) Create an instance thread of the Thread subclass, that is, create a thread object.
(3) The thread can be started by calling the start() method of thread.
package com.biyao.thread.example1; /** * Created by dalianlv * Create Date: 5:36:01 p.m. * Description:Inheriting Thread to create threads */ public class ThreadTest extends Thread{ public static void main(String[] args) throws InterruptedException { ThreadTest thread = new ThreadTest(); thread.setName("Thread_A"); System.out.println("I am Main Output in threads! After the output, open the thread Thread_A"); thread.start(); Thread.sleep(3000); System.out.println("I am Main Output in threads! Open threads Thread_A Later, delayed 3 seconds, I output!"); } @Override public void run(){ System.out.println("I did it through inheritance. Thread Class way to create a new thread to perform the task: output this line of text!"); } }
(2) Implementing Runnable Interface
Define the implementation class of the runnable interface and override the run() method of the interface. The run() method body is also the thread execution body of the thread.
(2). Create Runnable implements an instance of a class and creates a Thread object thread as the target of Thread, which is the real thread object.
(3) Invoke the thread object thread's start() method to start the thread.
package com.biyao.thread.example1; /** * Created by dalianlv * Create Date: 5:42:36 p.m. * Description:Implementing Runnable Interface to Create Threads */ public class RunnableTest implements Runnable{ public static void main(String[] args) throws InterruptedException { RunnableTest runnable = new RunnableTest(); Thread thread = new Thread(runnable); thread.setName("Thread_A"); System.out.println("I am Main Output in threads! After the output, open the thread Thread_A"); thread.start(); Thread.sleep(3000); System.out.println("I am Main Output in threads! Open threads Thread_A Later, delayed 3 seconds, I output!"); } @Override public void run() { System.out.println("I'm through implementation. Runnable Interface mode The task that a newly created thread needs to perform: Output this line of text!"); } }
(3) Implementation of Callnable interface combined with FutureTask mode
(1) Create the implementation class of Callable interface and implement the call() method, which acts as thread executor and has a return value;
(2) Create an instance of the Callable implementation class and wrap the Callable object with the FutureTask class, which encapsulates the return value of the call() method of the Callable object;
(3) Create Thread object thread using FutureTask object as the target of Thread object;
(4) Invoke the thread object thread start() method to start the thread;
(5) Call the get() method of the FutureTask object to get the return value after the execution of the sub-thread.
package com.biyao.thread.example1; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; /** * Created by dalianlv * Create Date: 11:39:52 p.m. * Description:Creating Threads by Implementing Callable Interface and FutureTask */ public class CallableThreadTest implements Callable<String>{ public static void main(String[] args) throws Exception{ CallableThreadTest ctt = new CallableThreadTest(); FutureTask<String> ft = new FutureTask<>(ctt); System.out.println("I am Main Output in threads! After the output, open the thread Thread_A"); Thread thread = new Thread(ft); thread.setName("Thread_A"); thread.start(); System.out.println("The return value of the subthread:"+ft.get()); Thread.sleep(3000); System.out.println("I am Main Output in threads! Open threads Thread_A Later, delayed 3 seconds, I output!"); } @Override public String call() throws Exception{ System.out.println("I'm through implementation. Callable Interface Combination FutureTask Way to create a new thread to perform the task: output this line of text!"); String returnStr = "ABCD"; System.out.println("The return value of thread execution is:"+returnStr+",I will be returned"); Thread.sleep(1000); return returnStr; } }
(4) Differences and Connections among the Three Modes of Creation
When multithreading is created by implementing Runnable and Callable interfaces
The advantage is that thread classes only implement Runnable or Callable interfaces and can inherit other classes. In this way, multiple threads can share the same target object, so it is very suitable for multiple threads to handle the same resource. Thus, CPU, code and data can be separated to form a clear model, which better reflects the idea of object-oriented.
The disadvantage is that programming is slightly more complex, and if you want to access the current thread, you must use the Thread.currentThread() method.
When creating multithreads by inheriting Thread classes
The advantage is that it's easy to write, and if you need to access the current thread, you don't need to use the Thread.currentThread() method to get the current thread directly using this.
The disadvantage is that thread classes have inherited Thread classes, so they can no longer inherit other parent classes.
The difference between Runnable and Callable
(1) Callable specifies call(),Runnable specifies run();
(2) Callable's task can return value after execution, while Runnable's task can't return value.
(3) The call method can throw an exception, but the run method can't.
(4). Running the Callable task can get a Future object that represents the result of asynchronous computation. It provides a way to check whether the calculation has been completed, to wait for the completion of the calculation, and to retrieve the results of the calculation. Through the Future object, we can know the execution of tasks, cancel the execution of tasks, and obtain the execution results.