Callable interface
Reference: blog.csdn.net/TZ845195485…
Review: two ways to create a thread
- Thread class inheritance
- Implement the Runnable interface
- Callable interface
- The thread pool
1.1. Inherit the Thread class
// Note: The printed results are executed alternately
public class ThreadDemo{
public static void main(String[] args) {
// create a subclass of Thread
MyThread myThread=new MyThread();
//5. Call start() to start the thread
// The run method is automatically called.
myThread.start();
for (int i = 0; i < 100; i++) {
System.out.println("I'm the main thread"+i); }}}class MyThread extends Thread{
//2. Override the run method
public void run(a){
//3. The code to be executed is written in the run method
for(int i=0; i<100; i++){ System.out.println("I'm a thread."+i); }}}Copy the code
1.2. Implement the Runnable interface
public class RunnableDemo {
public static void main(String[] args) {
//4. Create Runnable subclasses
MyRunnale mr=new MyRunnale();
//5. Pass the subclass object as an argument to the Thread constructor and start the Thread
//MyRunnale taget=mr; polymorphism
new Thread(mr).start();
for (int i = 0; i < 1000; i++) {
System.out.println("I'm the main thread"+i); }}}1. Define a class to implement Runnable
class MyRunnale implements Runnable{
//2. Override the run method
@Override
public void run(a) {
//3. The code to be executed is written in the run method
for (int i = 0; i < 1000; i++) {
System.out.println("I'm a thread."+i); }}}Copy the code
1.3. Differences between the two
View the source code
- Inheriting Thread: Due to subclass overrides
Thread
Of the classrun()
When the callstart()
, directly find the subclassrun()
methods - Implement Runnable: the constructor is passed in
Runnable
Start () calls run() internally to determine whether a reference to the Runnable member variable is nullrun()
The run time executes the subclass’s run() method
Inheriting the Thread
- The advantage is that you can use the methods in the Thread class directly, and the code is simple
- The downside is that if you already have a parent class, you can’t use this method
Implement the Runnable interface
- The advantage is that it doesn’t matter if the thread class you define has a parent class, because the parent class can implement the interface, and the interface can be multiple implementations
- The drawback is that the method in Thread cannot be used directly. The method of Thread can be obtained only after the Thread object is obtained. The code is complicated
2. Callable interface (create thread)
2.1. Code demonstration
public class ThreadNew {
public static void main(String[] args) {
//3. Create an object for the Callable interface implementation class
NumThead m=new NumThead();
//4. Pass the callable object as a parameter to the FutureTask constructor to create the FutureTask object
FutureTask futureTask = new FutureTask(m);
//5. Pass the FutureTask object as an argument to the constructor of the Thread class, create the Thread object, and call the start() method
new Thread(futureTask).start();
//6. Obtain the return value of the call method in the Callable interface
try {
// The return value of the get() method is the return value of the call method that implements the class override with the FutureTask constructor parameter callable
Object sum = futureTask.get();
System.out.println("The sum is :"+sum);
} catch(Exception e) { e.printStackTrace(); }}}1. Create an implementation class that implements the Callable interface
class NumThead implements Callable{
//2. Implement the call method and declare the operation that this thread needs to perform in call()
@Override
public Object call(a) throws Exception {
//public Integer call() throws Exception {
int sum=0;
for(int i=1; i<=100; i++){ System.out.println(i); sum+=i; }returnsum; }}Copy the code
2.2. Compare the Runnable and Callable interfaces
One feature that Runnable is missing is that we can’t make the thread return results when it terminates (that is, when run() completes). To support this functionality, Java provides a Callable interface
In the Callable interfacecall
Method and the Runnable interfacerun
Differences in methods
- The Callable
call()
Evaluates the result, and throws an exception if the result cannot be evaluated - In the Runnable
run()
Using the implementation interfaceRunnable
When the object creates a thread, starting the thread will result in the object being called in a separate thread of executionrun
methods - In summary:
run()
No return value, no exception thrown. whilecall()
If there is a return value, an exception will be thrown
// Implement the Runnable interface
class MyThread1 implements Runnable {
@Override
public void run(a) {}}// Implement the Callable interface
class MyThread2 implements Callable {
@Override
public Integer call(a) throws Exception {
return 200; }}Copy the code
Create a thread execution time difference
New Thread(new MyThread1(),”AA”).start(); New Thread(new MyThread2(),”BB”).start();
Since Thread constructors do not have Callable parameters, direct substitution is not possible. Instead, the Thread creation method is to find a class that is associated with the Runnable interface and the Callable interface, If you look at the source code, you can see that the Runnable interface has an implementation class called FutureTask (intermediate object). The constructor of FutureTask has a Callable parameter, so create thread objects from FutureTask as shown in the code above. The Thread is then started by calling the start method through Thread.
3, FutureTask
3.1 overview,
Inheritance system
FutureTask is the only implementation class for the Future interface
FutureTask implements both Runnable and Future interfaces. It can be either executed as a Runnable by the thread or as a Futrue to get the return value of a Callable
Constructor and common methods
FutureTask(Callable<> callable) // Create a FutureTask that, once run, executes the given Callable
FutureTask(Runnable runnable,V result) // Create a FutureTask that, once executed, executes the given Runnable side and schedules get to return the given result on successful completion
get() // Get the result
isDone() // Check whether the calculation is complete
Copy the code
3.2 FutureTask instantiation
FutureTask can be instantiated in two ways (the generic arguments used here), as shown in the two constructor ways
- The constructor passes in an implementation-class object that implements the Callable interface
- The constructor passes in the implementation-class object that implements the Runnable interface and returns the result,
// Implement the Callable interface
class MyThread2 implements Callable<Integer> {
@Override
public Integer call(a) throws Exception {
return 200;
}
}
FutureTask<Integer> futureTask1 = new FutureTask<>(new MyThread2());
Copy the code
Given the new jdK8 feature, which is a functional interface, it can be simplified using lambda expressions
/ / lambda expressions
FutureTask<Integer> futureTask2 = new FutureTask<>(()->{
System.out.println(Thread.currentThread().getName()+" come in callable");
return 1024;
});
Copy the code
3.3. Create a thread
Create thread 3: implement callable interface -JDK 5.0 new
- Create an implementation class that implements the Callable interface
- Implement the Call method to declare the operations this thread needs to perform in
call()
In the - create
callable
Object of the interface implementation class - Will this
callable
Object as a parameter toFutureTask
Constructor, createFutureTask
The object of - will
FutureTask
Object is passed as an argument to the constructor of the Thread class, the Thread object is created, and star is called, i.enew Thread(futureTask2,"lucy").start();
- Get the return value of the call method in the Callable interface:
System.out.println(futureTask2.get());
public class ThreadNew {
public static void main(String[] args) {
//3. Create an object for the Callable interface implementation class
NumThead m=new NumThead();
//4. Pass the callable object as a parameter to the FutureTask constructor to create the FutureTask object
FutureTask futureTask = new FutureTask(m);
//5. Pass the FutureTask object as an argument to the constructor of the Thread class, create the Thread object, and call the start() method
The FutureTask class inherits the Runnable interface
//new Runnable = futrueTask;
new Thread(futureTask).start();
//6. Obtain the return value of the call method in the Callable interface
try {
// The return value of the get() method is the return value of the call method that implements the class override with the FutureTask constructor parameter callable
Object sum = futureTask.get();
System.out.println("The sum is :"+sum);
} catch(Exception e) { e.printStackTrace(); }}}1. Create an implementation class that implements the Callable interface
class NumThead implements Callable{
// class NumThead implements Callable
{
//2. Implement the call method and declare the operation that this thread needs to perform in call()
@Override
public Object call(a) throws Exception {
//public Integer call() throws Exception {
int sum=0;
for(int i=1; i<=100; i++){ System.out.println(i); sum+=i; }returnsum; }}Copy the code
FutureTask is when a single thread is started to complete a particular task without affecting the main task, and then the main thread continues the results of the single thread (which is aggregated to the main thread only once). If the main thread starts the single thread later, the result can be obtained directly because it has already been executed once before.
3.4 FutureTask principle analysis
Why have a Callable interface when you have Runnable? Let’s say there are four programs that need to be executed, and the third program takes a long time,
Runnable
Interfaces execute sequentially, from top to bottom, and wait for the third program to finish before executing the fourthCallable
The interface will open a long third program to a separate thread to execute, the first, second, fourth thread execution is not affected- For example, if the main thread asks a child thread to perform a task, the child thread may be time-consuming. If it starts the child thread to perform the task, the main thread will do something else and fetch the result of the subtask later
Example:
- The teacher on the class, thirsty, to buy water is not appropriate, lecture threads continue, I can single thread to find monitor for help. Buy water and put it on the table. I’ll get it when I need it.
- 4 students, A calculate 1+20, B calculate 21+30, C calculate 31* to 40, D calculate 41+50, isn’t it A bit too much computation for C? FutureTask will set up A single thread for C to calculate, I will first summarize ABD, and then summarize it for C when C is finished to get the final result
- College entrance examination: will do first, will not do in the back
3.5 matters needing attention
Question 1
- The meaning of FutureTask is that my main thread and child threads execute down in sequence. And after starting a thread to execute, I can get the return value of the thread at any time to summarize, without having to execute the thread again.
- The get() method is recommended to be placed on the last line to prevent thread blocking (which happens once the get() method is called, whether the calculation is complete or not), but you can also get it using asynchronous communication, as shown in Question 2
- The get method will only evaluate once, and the rest will not be evaluated
- A FutureTask is called only once by multiple threads calling the call() method
- If you need to call the Call method multiple times, you need multiple FutureTasks
The instance
public class CallableDemo {
public static void main(String[] args) throws Exception{
CallAble c=new CallAble();
/ / a FutureTask
FutureTask<Integer> futureTask=new FutureTask<>(c);
// Multiple threads calling the call() method are called only once
new Thread(futureTask,"Thread A").start();
new Thread(futureTask,"Thread B").start();
Integer integer = futureTask.get();// The get() method is recommended on the last line to prevent thread blocking
System.out.println("integer = "+ integer); }}class CallAble implements Callable<Integer>{
@Override
public Integer call(a) throws Exception {
System.out.println("Welcome to call the call method.");
return 6; }}Copy the code
Results:
You are welcome to call the call method integer =6
Copy the code
Question 2:
IsDone () polling (we’ll use CompletableFuture to solve get() blocking later)
- Polling consumes intrepid CPU resources and does not always get results in a timely manner
- If you want to get results asynchronously, you will usually get results by polling, and try not to block
public class FutureTaskTest {
public static void main(String[] args) throws Exception{
FutureTask futureTask = new FutureTask(()->{
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"\t"+"coming......");
return 1024;
});
new Thread(futureTask).start();
If futuretask.get () is placed before the main thread, the main thread will block
//Object o = futureTask.get();
/*Object o = futureTask.get(); System.out.println(" See you there, see you there, see you there, see you there "+o); * /
//2
/ / System. Out.println (Thread. CurrentThread (). The getName () + "\ t" + "Thread to..." );
//Object o2 = futureTask.get(2L, TimeUnit.SECONDS);
//3. Use polling
while(true) {if(futureTask.isDone()){
System.out.println("To resolve using polling, the value is :"+futureTask.get());
break;
}else{
System.out.println("Blocking **********"); }}}}Copy the code