Интерфейсы Callable и Future в Java


Deprecated: Function create_function() is deprecated in /var/www/admin/www/pro-java.ru/wp-content/plugins/wp-spamshield/wp-spamshield.php on line 2033

Интерфейсы Callable и Future в JavaИнтерфейс Runnable инкапсулирует задачу, выполняющуюся асинхронно. Вы можете воспринимать это как асинхронный метод без параметров и возвращаемого значения. Callable подобен Runnable, но с возвратом значения. Интерфейс Callable является параметризованным типом, с единственным общедоступным методом call().

public interface Callable;
{
V call() throws Exception;
}

Параметр представляет собой тип возвращаемого значения. Например, Callable представляет асинхронное вычисление, которое в конечном итоге возвращает объект Integer.

Future хранит результат асинхронного вычисления. Вы можете запустить вычисление, предоставив кому-либо объект Future, и забыть о нем. Владелец объекта Future может получить результат, когда он будет готов.

Интерфейс Future имеет следующие методы.

public interface Future
{
V get() throws . . .;
V get(long timeout, TimeUnit unit) throws . . .;
boolean isCancelled();
boolean isDone();
}

Вызов первого метода get() устанавливает блокировку до тех пор, пока не завершится вычисление. Второй метод генерирует исключение TimeoutException, если истекает таймаут до завершения вычислений. Если прерывается поток, выполняющий вычисление, оба метода генерируют исключение InterruptedException. Если вычисление уже завершено, get() немедленно возвращает управление.

Метод isDone() возвращает false, если вычисление продолжается, и true - если оно завершено.

Вы можете прервать вычисление,вызвав метод Cancel(). Если вычисление еще не стартовало, оно отменяется и уже не будет запущено. Если же вычисление уже идет, оно прерывается в случае равенства true параметра mayInterrupt.

Любите задавать вопросы в Аске, но Вам не хватает подписчиков и лайков — попробуйте заказать их на сервисе avi1.ru. Здесь Вы получите данные ресурсы по очень дешевой стоимости, а также с высококачественным исполнением от лучших сотрудников техподдержки.

Класс-оболочка FutureTask представляет собой удобный механизм для превращения Callable одновременно в Future и Runnable, реализуя оба интерфейса.

Например:

Callable myComputation = . . .;
FutureTask task = new FutureTask(myComputation);
Thread t = ne Thread(task);  //  Runnable
t.start();
...
Integer result = task.get();  //  Future

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

class MatchCounter implements Callable{
public MatchCounter(File directory, String keyword) { . . . }
public Integer call() { . . . }  //    
}

Сконструируем объект из MatchCounter и используем его для запуска потока:

FutureTask(counter);
Thread t = new Thread(task);
t.start();

И, наконец, напечатаем результат:

System.out.println(task.get() + "  .");

Конечно, вызов get() устанавливает блокировку до тех пор, пока не будет готов результат.

Внутри метода call() мы используем тот же механизм рекурсивно. Для каждого подкаталога создадим новый MathCounter и запустим поток для него. Также мы спрячем объект FutureTask в ArrayList<Future>. И в конце сложим все результаты:

for (Future result : results)
count += result.get();

Каждый вызов get() устанавливает блокировку до тех пор, пока не будет готов результат. Конечно, потоки работают параллельно, так что есть шанс, что результаты будут готовы почти одновременно.

Вот полный код нашей программы:

import java.io.*;
import java.util.*;
import java.util.concurrent.*;

import javax.imageio.stream.FileImageInputStream;

public class FutureTest {

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        System.out.print("   (, /usr/loacl/jdk/lib): ");
        String directory = in.nextLine();
        System.out.print("   (, volatile): ");
        String keyword = in.nextLine();
        MatchCounter counter = new MatchCounter(new File(directory), keyword);
        FutureTask task = new FutureTask(counter);
        Thread t = new Thread(task);
        t.start();
        try
        {
            System.out.println(task.get() + "  .");
        }
        catch(ExecutionException e)
        {
            e.printStackTrace();
        }
        catch (InterruptedException e)
        {
        }
    }

}
/**
 *          ,
 *      .
 */
class MatchCounter implements Callable
{
/**
 *  MatchCounter
 * @param directory ,    
 * @param keyword   
 */
public MatchCounter(File directory, String keyword)
{
this.directory = directory;
this.keyword = keyword;
}
public Integer call()
{
    count = 0;
    try
    {
        File[] files = directory.listFiles();
        ArrayList results = new ArrayList();
        for(File file : files)
            if(file.isDirectory())
            {
                MatchCounter counter = new MatchCounter(file, keyword);
                FutureTask task = new FutureTask(counter);
                results.add(task);
                Thread t = new Thread(task);
                t.start();
            }
            else
            {
                if(search(file)) count++;
            }
        for(Future result : results)
            try
        {
                count+= result.get();
        }
        catch (ExecutionException e)
        {
            e.printStackTrace();
        }
    }
    catch(InterruptedException e)
    {
    }
    return count;
}

/**
 *      .
 * @param file ,    
 * return true,     
 */
public boolean search(File file)
{
    try
    {
        Scanner in = new Scanner((Readable) new FileImageInputStream(file));
        boolean found = false;
        while(!found &amp;&amp; in.hasNextLine())
        {
            String line = in.nextLine();
            if(line.contains(keyword)) found = true;
        }
        in.close();
        return found;
    }
    catch (IOException e)
    {
        return false;
    }
}
private File directory;
private String keyword;
private int count;
}

Комментариев 5 на “Интерфейсы Callable и Future в Java

  1. Спасибо Вам огромное за труды. Очень хорошие статьи! Читаю Вас почти каждый день.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *