Parallel programming using Callable and Future
The most common way to perform parallel programming in Java is to inherit the Thread class or implement the Runnable interface. The disadvantage of these two methods is that the execution result cannot be obtained directly after the task is completed, and it must be communicated through shared variables or inter-threads, which is inconvenient to use.
Starting from Java 1.5, Callable and Future interfaces are provided. By using them, you can get the execution result after the task is executed.
Let's learn how to use Callable, Future and FutureTask.
Callable interface
The Callable interface is located in the java.util.concurrent package. This is a generic interface that only declares a call() method:
public interface Callable<T> { T call() throws Exception;}Generally, it is used in conjunction with the ExecutorService interface. Several overloaded submit methods are declared in the ExecutorService interface:
<T> Future<T> submit(Callable<T> task);<T> Future<T> submit(Runnable task, T result);Future<?> submit(Runnable task);
The parameter type in the first submit method is Callable, and the other two are not covered by this article for the time being.
Future and FutureTask
The implementation class of the Future interface can perform operations such as canceling, querying, and obtaining results on Runnable or Callable tasks.
The Future interface is also located under the java.util.concurrent package:
public interface Future<T> { /** *Cancel task*@param mayInterruptIfRunning *Does it allow cancellation of tasks that are being executed but not completed? If true is set, it means that the task in the process can be cancelled *If the task is being executed, it returns true *If the task has not been executed yet, it returns true whether mayInterruptIfRunning is true or false */ boolean cancel(boolean mayInterruptIfRunning); /** *Does the task be cancelled successfully? If it is cancelled successfully before the task is completed normally, it returns true */ boolean isCancelled(); /** *Does the task be completed*/ boolean isDone(); /** *Get the execution result through blocking*/ T get() throws InterruptedException, ExecutionException; /** *Get the execution result through blocking. If no return is returned within the specified time, return null */ T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;}To sum up, Future provides three functions:
Determine whether the task is completed and can interrupt the task and obtain the result of the task execution
JDK provides us with a Future interface implementation class FutureTask, which has the following two constructors.
public FutureTask(Callable<T> callable) {}public FutureTask(Runnable runnable, T result) {} Sample code
Using Callable, Future
import java.util.concurrent.*;public class Test { public static void main(String[] args) { ExecutorService executorService = Executors.newCachedThreadPool(); Task task = new Task(); Future<Integer> future = executorService.submit(task); executorService.shutdown(); System.out.println("The main thread is executing the task..."); try { Thread.sleep(2000); } catch(InterruptedException ex) { ex.printStackTrace(); } try { System.out.println("task run result:"+future.get()); } catch (InterruptedException ex) { ex.printStackTrace(); } catch (ExecutionException ex) { ex.printStackTrace(); } System.out.println("All tasks have been executed"); }}class Task implements Callable<Integer>{ @Override public Integer call() throws Exception { System.out.println("Child thread is executing task..."); //Simulation task takes time Thread.sleep(5000); return 1000; }}Execution results:
The child thread is executing the task...The main thread is executing the task...task operation result: 1000 all tasks have been executed
Use Callable, FutureTask
import java.util.concurrent.*;public class Test { public static void main(String[] args) { ExecutorService executorService = Executors.newCachedThreadPool(); Task task = new Task(); FutureTask<Integer> futureTask = new FutureTask<Integer>(task); executorService.submit(futureTask); executorService.shutdown(); System.out.println("The main thread is executing the task..."); try { Thread.sleep(2000); } catch (InterruptedException ex) { ex.printStackTrace(); } try { System.out.println("task run result:"+futureTask.get()); } catch (InterruptedException ex) { ex.printStackTrace(); } catch (ExecutionException ex) { ex.printStackTrace(); } System.out.println("All tasks are executed"); }}class Task implements Callable<Integer>{ @Override public Integer call() throws Exception { System.out.println("The child thread is executing the task..."); //Simulating the task takes Thread.sleep(5000); return 1000; }}Execution results:
The child thread is executing the task...The main thread is executing the task...task operation result: 1000 all tasks have been executed
Summarize
The above is all the content of this article about using Callable and Future for parallel programming in Java. I hope it will be helpful to everyone. Interested friends can continue to refer to other related topics on this site. If there are any shortcomings, please leave a message to point it out. Thank you friends for your support for this site!