Поиск по сайту:

Пример вызываемого будущего Java


Java Callable и Future часто используются в многопоточном программировании. В последних нескольких сообщениях мы многое узнали о потоках Java, но иногда нам хочется, чтобы поток мог возвращать какое-то значение, которое мы можем использовать. Java 5 представила интерфейс java.util.concurrent.Callable в пакете параллелизма, который похож на интерфейс Runnable, но может возвращать любой объект и может вызывать исключение.

Java вызываемый

Будущее Java

Задачи Java Callable возвращают объект java.util.concurrent.Future. Используя объект Java Future, мы можем узнать статус задачи Callable и получить возвращенный объект. Он предоставляет метод get(), который может дождаться завершения Callable, а затем вернуть результат. Java Future предоставляет метод cancel() для отмены связанной вызываемой задачи. Существует перегруженная версия метода get(), в которой мы можем указать время ожидания результата, это полезно, чтобы избежать блокировки текущего потока на более длительное время. Существуют методы isDone() и isCancelled() для определения текущего состояния связанной вызываемой задачи. Вот простой пример задачи Java Callable, которая возвращает имя потока, выполняющего задачу, через одну секунду. Мы используем платформу Executor для параллельного выполнения 100 задач и используем Java Future для получения результата отправленных задач.

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<String> {

    @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<Future<String>> list = new ArrayList<Future<String>>();
        //Create MyCallable instance
        Callable<String> callable = new MyCallable();
        for(int i=0; i< 100; i++){
            //submit Callable tasks to be executed by thread pool
            Future<String> future = executor.submit(callable);
            //add Future to the list, we can get return value using Future
            list.add(future);
        }
        for(Future<String> 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();
    }

}

Как только мы выполним приведенную выше программу, вы заметите задержку вывода, потому что метод java Future get() ожидает завершения вызываемой задачи java. Также обратите внимание, что эти задачи выполняются только 10 потоками. Вот фрагмент вывода вышеуказанной программы.

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
...

Совет: что, если мы хотим переопределить некоторые методы интерфейса Java Future, например переопределить метод get() для тайм-аута после некоторого времени по умолчанию, а не ждать бесконечно, в этом случае класс Java FutureTask пригодится. это базовая реализация интерфейса Future. Ознакомьтесь с примером Java FutureTask, чтобы узнать больше об этом классе.