Callable examples in java

Concurrent интерфейсы Callable, Future

При работе многопоточного приложения часто необходимо получение от потока результата его деятельности в виде некоторого объекта. Эту задачу можно решить с использованием интерфейсов Callable и Future. Совместное использование двух реализаций данных интерфейсов позволяет получить результат в виде некоторого объекта.

Интерфейс Callable

Интерфейс Callable очень похож на интерфейс Runnable. Объекты, реализующие данные интерфейсы, исполняются другим потоком. Однако, в отличие от Runnable, интерфейс Callable использует Generic’и для определения типа возвращаемого объекта. Runnable содержит метод run(), описывающий действие потока во время выполнения, а Callable – метод call().

С документацией интерфейса Callable можно познакомиться здесь.

Интерфейс Future

Интерфейс Future также, как и интерфейс Callable, использует Generic’и. Методы интерфейса можно использовать для проверки завершения работы потока, ожидания завершения и получения результата. Результат выполнения может быть получен методом get, если поток завершил работу. Прервать выполнения задачи можно методом cancel. Дополнительные методы позволяют определить завершение задачи : нормальное или прерванное. Если задача завершена, то прервать ее уже невозможно.

Методы интерфейса Future

Метод Описание
cancel (boolean mayInterruptIfRunning) попытка завершения задачи
V get() ожидание (при необходимости) завершения задачи, после чего можно будет получить результат
V get(long timeout, TimeUnit unit) ожидание (при необходимости) завершения задачи в течение определенного времени, после чего можно будет получить результат
isCancelled() вернет true, если выполнение задачи будет прервано прежде завершения
isDone() вернет true, если задача завершена

С документацией интерфейса Future можно познакомиться здесь.

Пример использования интерфейсов Callable, Future

Рассмотрим простейший пример использования интерфейсов Callable и Future. Основная идея данного примера – показать, как можно, используя Future, узнать статус Callable потока и получить возвращенный объект. В примере используется объект executor типа ExecutorService, формирующий пул из трех потоков. Метод submit с параметром Callable возвращает объект Future для каждого из стартуемого потоков.

import java.util.Date; import java.util.List; import java.util.ArrayList; import java.util.concurrent.Future; import java.util.concurrent.Callable; import java.util.concurrent.Executors; import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutionException; import java.text.SimpleDateFormat; public class CallableExample < public CallableExample() < // Определяем пул из трех потоков ExecutorService executor; executor = Executors.newFixedThreadPool(3); // Список ассоциированных с Callable задач Future List> futures; futures = new ArrayList>(); // Создание экземпляра Callable класса Callable callable = new CallableClass(); for (int i = 0; i < 3; i++)< /* * Стартуем возвращаюший результат исполнения * в виде объекта Future поток */ Futurefuture; future = executor.submit(callable); /* * Добавляем объект Future в список для * отображения результат выполнения (получение * наименования потока) */ futures.add(future); > SimpleDateFormat sdf; sdf = new SimpleDateFormat("HH:mm:ss "); for (Future future : futures) < try < // Выводим в консоль полученное значение String text = sdf.format(new Date()) + future.get(); System.out.println(text); >catch (InterruptedException | ExecutionException e) <> > // Останавливаем пул потоков executor.shutdown(); > //----------------------------------------------------- // Класс, реализующий интерфейс Callable class CallableClass implements Callable  < @Override public String call() throws Exception < Thread.sleep(1000); // наименование потока, выполняющего // callable задачу return Thread.currentThread().getName(); >> //----------------------------------------------------- public static void main(String args[]) < new CallableExample(); >>

Класс CallableClass, реализующий интерфейс Callable, использует объект String в качестве generic’a. Соответственно и каждый объект Future также должен использовать тип объекта String.

Результат выполнения

Перед остановкой пула потоков в консоль выводятся наименования потока. Т.е. в примере демонстрируется возможность не прямого обращения к методу call класса, реализующего интерфейс Callable, а косвенно через объект Future, полученного при старте потока.

17:41:16 pool-1-thread-1 17:41:19 pool-1-thread-2 17:41:19 pool-1-thread-3

Источник

Java Callable Future Example

One of the benefits of the Java executor framework is that we can run concurrent tasks that may return a single result after processing the tasks. The Java Concurrency API achieves this with the following two interfaces Callable and Future .

In this tutorial, we will learn to execute Callable tasks (which return a result of type Future after execution) using ExecutorService implementations in this simple Callable Future example.

1. Java Callable and Future Interfaces

In Java concurrency, Callable represents a task that returns a result. Executors can run callable tasks – concurrently. Since Java 8, it is a functional interface and can therefore be used as the assignment target for a lambda expression or method reference.

Callable interface has the call() method. In this method, we have to implement the logic of a task. The Callable interface is a parameterized interface, meaning we have to indicate the type of data the call() method will return.

@FunctionalInterface public interface Callable < /** * Computes a result, or throws an exception if unable to do so. * * @return computed result * @throws Exception if unable to compute a result */ V call() throws Exception; >

Future interface has methods to obtain the result generated by a Callable object and manage its state. It represents the result of an asynchronous computation. The result can only be retrieved using method get() when the computation has been completed, blocking if necessary until it is ready.

The cancellation of a task is performed by the cancel() method. Once a computation has been completed, the computation cannot be canceled.

2. Java Callable Future Example

In this example, we are executing a task that returns its name when it’s completed. We will use ExecutorService to execute this task and print its name in main thread after it has been completed.

The Future.get() is used for blocking the main thread execution until the corresponding task submitted to the executor is not completed. It can, optionally, take a timeout period after which it will unblock with a TimeOutException.

import java.time.LocalDateTime; import java.util.concurrent.*; public class CallableFutureExample < public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException < ExecutorService executor = Executors.newFixedThreadPool(1); Futurefuture = executor.submit(new Work("Demo-Task")); String completedThread = future.get(10, TimeUnit.SECONDS); System.out.println("Thread completed : " + completedThread); > > class Work implements Callable  < private final String name; public Work(String name) @Override public String call() < System.out.println("Task [" + name + "] executed on : " + LocalDateTime.now().toString()); return name; >>
Task [Demo-Task] executed on : 2022-08-07T15:57:33.372000500 Thread completed : Demo-Task 

Here we sent a Callable object to be executed in an executor using the submit() method. This method receives a Callable object as a parameter and returns a Future object that we can use with two main objectives –

  1. We can control the status of the task – we can cancel the task and check if it has finished. For this purpose, we can use the isDone() method to check if the tasks had finished.
  2. We can get the result returned by the call() method. For this purpose, we have used the get() method. This method waits until the Callable object has finished the execution of the call() method and has returned its result. If the thread is interrupted while the get() method is waiting for the result, it throws an InterruptedException exception. If the call() method throws an exception, this method throws an ExecutionException exception.

In this tutorial, we learned the basics of the Callable and Future interfaces and how to execute callable tasks with ExecutorService. We learned to control the execution using the isDone(), cancel() and get() methods.

Источник

Java Callable Future Example

Java Callable Future Example

While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.

Java Callable and Future are used a lot in multithreaded programming. In last few posts, we learned a lot about java threads but sometimes we wish that a thread could return some value that we can use. Java 5 introduced java.util.concurrent.Callable interface in concurrency package that is similar to Runnable interface but it can return any Object and able to throw Exception.

Java Callable

java Callable, java Future, java callable example, java executorservice callable

Java Callable interface use Generic to define the return type of Object. Executors class provide useful methods to execute Java Callable in a thread pool. Since callable tasks run in parallel, we have to wait for the returned Object.

Java Future

Java Callable tasks return java.util.concurrent.Future object. Using Java Future object, we can find out the status of the Callable task and get the returned Object. It provides get() method that can wait for the Callable to finish and then return the result. Java Future provides cancel() method to cancel the associated Callable task. There is an overloaded version of get() method where we can specify the time to wait for the result, it’s useful to avoid current thread getting blocked for longer time. There are isDone() and isCancelled() methods to find out the current status of associated Callable task. Here is a simple example of Java Callable task that returns the name of thread executing the task after one second. We are using Executor framework to execute 100 tasks in parallel and use Java Future to get the result of the submitted tasks.

package com.journaldev.threads; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; public class MyCallable implements Callable  < @Override public String call() throws Exception < Thread.sleep(1000); //return the thread name executing this callable task return Thread.currentThread().getName(); >public static void main(String args[])< //Get ExecutorService from Executors utility class, thread pool size is 10 ExecutorService executor = Executors.newFixedThreadPool(10); //create a list to hold the Future object associated with Callable List list = new ArrayList(); //Create MyCallable instance Callable callable = new MyCallable(); for(int i=0; i < 100; i++)< //submit Callable tasks to be executed by thread pool Futurefuture = executor.submit(callable); //add Future to the list, we can get return value using Future list.add(future); > for(Future fut : list) < try < //print the return value of Future, notice the output delay in console // because Future.get() waits for task to get completed System.out.println(new Date()+ "::"+fut.get()); >catch (InterruptedException | ExecutionException e) < e.printStackTrace(); >> //shut down the executor service now executor.shutdown(); > > 

Once we execute the above program, you will notice the delay in output because java Future get() method waits for the java callable task to complete. Also notice that there are only 10 threads executing these tasks. Here is snippet of the output of above program.

Mon Dec 31 20:40:15 PST 2012::pool-1-thread-1 Mon Dec 31 20:40:16 PST 2012::pool-1-thread-2 Mon Dec 31 20:40:16 PST 2012::pool-1-thread-3 Mon Dec 31 20:40:16 PST 2012::pool-1-thread-4 Mon Dec 31 20:40:16 PST 2012::pool-1-thread-5 Mon Dec 31 20:40:16 PST 2012::pool-1-thread-6 Mon Dec 31 20:40:16 PST 2012::pool-1-thread-7 Mon Dec 31 20:40:16 PST 2012::pool-1-thread-8 Mon Dec 31 20:40:16 PST 2012::pool-1-thread-9 Mon Dec 31 20:40:16 PST 2012::pool-1-thread-10 Mon Dec 31 20:40:16 PST 2012::pool-1-thread-2 . 

Tip: What if we want to override some of the methods of Java Future interface, for example overriding get() method to timeout after some default time rather than waiting indefinitely, in this case Java FutureTask class comes handy that is the base implementation of Future interface. Check out Java FutureTask Example to learn more about this class.

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases. Learn more about us

Источник

Читайте также:  Python index in for cycle
Оцените статью