Future pattern

The core of the future mode is that the waiting time of the main function is removed, and the time period that originally needs to be waited can be used to process other business logic;

This article only gives the JDK built-in implementation

scenes to be used

    When shopping online, when you fancy a certain product, you can submit an order. When the order is processed, you can wait for the product to be delivered to your door at home. The seller will pick up the product from the warehouse according to the order and deliver it to the customer. , customers can continue to do their own work after submitting the order, and do not have to wait for the goods to be delivered to their hands.

Simulate a long task

import java.util.concurrent.Callable;

public class RealData implements Callable<String> {
    private String para;
    public RealData(String para){
    	this.para=para;
    }
	@Override
	public String call() throws Exception {
    	
    	StringBuffer sb=new StringBuffer();
        for (int i = 0; i < 10; i++) {
        	sb.append(para);
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
            }
        }
        return sb.toString();
	}
}

Simulate the main task

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;

public class Main {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
    	//Construct FutureTask
        FutureTask<String> future = new FutureTask<String>(new RealData("a"));
        ExecutorService executor = Executors.newFixedThreadPool(1);
        //Execute FutureTask, which is equivalent to client.request("a") in the above example to send a request
        //Open the thread here to execute the call() of RealData
        executor.submit(future);
        System.out.println("Request completed");
        try {
        //Additional data operations can still be done here, and sleep is used here instead of other business logic processing
            Thread.sleep(2000);
        } catch (InterruptedException e) {
        }
        // Equivalent to data.getContent() in the above example, get the return value of the call() method
        //If the call() method is not completed at this time, it will still wait
        System.out.println("数据 = " + future.get());
    }
}

This has been explained here, what? Don't you know about FutureTask yet? Then let's analyze the difference between Future and FutureTask

Future is to cancel the execution result of a specific Runnable or Callable task, query whether it is completed, and obtain the result. If necessary, the execution result can be obtained through the get method, which will block until the task returns the result.

The Future class is located under the java.util.concurrent package, which is an interface:

/**
     * Attempts to cancel execution of this task.  This attempt will
     * fail if the task has already completed, has already been cancelled,
     * or could not be cancelled for some other reason. If successful,
     * and this task has not started when {@code cancel} is called,
     * this task should never run.  If the task has already started,
     * then the {@code mayInterruptIfRunning} parameter determines
     * whether the thread executing this task should be interrupted in
     * an attempt to stop the task.
     *
     * <p>After this method returns, subsequent calls to {@link #isDone} will
     * always return {@code true}.  Subsequent calls to {@link #isCancelled}
     * will always return {@code true} if this method returned {@code true}.
     *
     * @param mayInterruptIfRunning {@code true} if the thread executing this
     * task should be interrupted; otherwise, in-progress tasks are allowed
     * to complete
     * @return {@code false} if the task could not be cancelled,
     * typically because it has already completed normally;
     * {@code true} otherwise
     */
    boolean cancel(boolean mayInterruptIfRunning);

    /**
     * Returns {@code true} if this task was cancelled before it completed
     * normally.
     *
     * @return {@code true} if this task was cancelled before it completed
     */
    boolean isCancelled();

    /**
     * Returns {@code true} if this task completed.
     *
     * Completion may be due to normal termination, an exception, or
     * cancellation -- in all of these cases, this method will return
     * {@code true}.
     *
     * @return {@code true} if this task completed
     */
    boolean isDone();

    /**
     * Waits if necessary for the computation to complete, and then
     * retrieves its result.
     *
     * @return the computed result
     * @throws CancellationException if the computation was cancelled
     * @throws ExecutionException if the computation threw an
     * exception
     * @throws InterruptedException if the current thread was interrupted
     * while waiting
     */
    V get() throws InterruptedException, ExecutionException;

    /**
     * Waits if necessary for at most the given time for the computation
     * to complete, and then retrieves its result, if available.
     *
     * @param timeout the maximum time to wait
     * @param unit the time unit of the timeout argument
     * @return the computed result
     * @throws CancellationException if the computation was cancelled
     * @throws ExecutionException if the computation threw an
     * exception
     * @throws InterruptedException if the current thread was interrupted
     * while waiting
     * @throws TimeoutException if the wait timed out
     */
    V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;
Five methods are declared in the Future interface, and the function of each method is explained in turn:
1) The cancel method is used to cancel the task. It returns true if the cancel task is successful, and returns false if the cancel task fails. The parameter mayInterruptIfRunning indicates whether it is allowed to cancel the task that is being executed but not completed. If it is set to true, it indicates that the task in the execution process can be canceled. If the task has been completed, whether mayInterruptIfRunning is true or false, this method must return false, that is, if the completed task is canceled, it will return false; if the task is executing, if mayInterruptIfRunning is set to true, it will return true, if mayInterruptIfRunning is set to false , then returns false; if the task has not been executed, whether mayInterruptIfRunning is true or false, it must return true.
2) The isCancelled method indicates whether the task was canceled successfully. If the task was canceled successfully before the normal completion of the task, it returns true.
3) The isDone method indicates whether the task has been completed. If the task is completed, it will return true;
4) The get() method is used to obtain the execution result. This method will block and will not return until the task is executed;
5) get(long timeout, TimeUnit unit) is used to obtain the execution result. If the result is not obtained within the specified time, it will directly return null.
  That is to say, Future provides three functions:
   1) Determine whether the task is completed;
  2) Can interrupt the task;
  3) Can obtain the task execution result.

  Because Future is just an interface, it cannot be used to create objects directly, so there is the following FutureTask.
Let's first look at the implementation of FutureTask:
public class FutureTask<V> implements RunnableFuture<V> {...}
The FutureTask class implements the RunnableFuture interface. Let's take a look at the implementation of the RunnableFuture interface:
public interface RunnableFuture<V> extends Runnable, Future<V> {
    /**
     * Sets this Future to the result of its computation
     * unless it has been cancelled.
     */
    void run();
}
  It can be seen that RunnableFuture inherits Runnable interface and Future interface, and FutureTask implements RunnableFuture interface. So it can be executed by the thread as Runnable, and can get the return value of Callable as Future.
FutureTask provides 2 constructors:
    /**
     * Creates a {@code FutureTask} that will, upon running, execute the
     * given {@code Callable}.
     *
     * @param  callable the callable task
     * @throws NullPointerException if the callable is null
     */
    public FutureTask(Callable<V> callable) {
        if (callable == null)
            throw new NullPointerException();
        this.callable = callable;
        this.state = NEW;       // ensure visibility of callable
    }
    /**
     * Creates a {@code FutureTask} that will, upon running, execute the
     * given {@code Runnable}, and arrange that {@code get} will return the
     * given result on successful completion.
     *
     * @param runnable the runnable task
     * @param result the result to return on successful completion. If
     * you don't need a particular result, consider using
     * constructions of the form:
     * {@code Future<?> f = new FutureTask<Void>(runnable, null)}
     * @throws NullPointerException if the runnable is null
     */
    public FutureTask(Runnable runnable, V result) {
        this.callable = Executors.callable(runnable, result);
        this.state = NEW;       // ensure visibility of callable
    }
In fact, FutureTask is the only implementation class of the Future interface


Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325406289&siteId=291194637