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 overridesThreadOf the classrun()When the callstart(), directly find the subclassrun()methods
  • Implement Runnable: the constructor is passed inRunnableStart () 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 interfacecallMethod and the Runnable interfacerunDifferences in methods

  • The Callablecall()Evaluates the result, and throws an exception if the result cannot be evaluated
  • In the Runnablerun()Using the implementation interfaceRunnableWhen the object creates a thread, starting the thread will result in the object being called in a separate thread of executionrunmethods
  • 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 incall()In the
  • createcallableObject of the interface implementation class
  • Will thiscallableObject as a parameter toFutureTaskConstructor, createFutureTaskThe object of
  • willFutureTaskObject 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,

  • RunnableInterfaces execute sequentially, from top to bottom, and wait for the third program to finish before executing the fourth
  • CallableThe 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

  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.
  2. 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
  3. The get method will only evaluate once, and the rest will not be evaluated
  4. A FutureTask is called only once by multiple threads calling the call() method
  5. 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)

  1. Polling consumes intrepid CPU resources and does not always get results in a timely manner
  2. 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