FutureTask и неблокирующая проверка завершения

Рейтинг: 0Ответов: 1Опубликовано: 28.10.2014

Как известно, метод get у фьючера приводит к блокировке текущего потока. Требуется получить результат без блокировки. Вариант с методами isDone/isCancelled и с последующим вызовом get приводит к эксепшену:

java.util.concurrent.ExecutionException: java.lang.IndexOutOfBoundsException at java.util.concurrent.FutureTask.report(FutureTask.java:122) at java.util.concurrent.FutureTask.get(FutureTask.java:188)

Сам код большой, поэтому приведу только вариант, где эксепшен воспроизводится (2-й while для воспроизведения ошибки):

        ExecutorService executor = Executors.newFixedThreadPool(threadsNum);
        List<Future<ResultWrapper>> futures = new LinkedList<Future<ResultWrapper>>();
        class DownloadCallable implements Callable<ResultWrapper> {
           @Override
           public ResultWrapper call() {
               ...
            }
         ...
        dc = new DownloadCallable();
        futures.add(executor.submit(dc));
            ...             
        final Iterator<Future<ResultWrapper>> it = futures.iterator();
        try {
            while (it.hasNext()) {
                final Future<ResultWrapper> fut = it.next();
                while (!(fut.isDone() || fut.isCancelled())) {
                    Thread.sleep(DATA_TIMEOUT);
                }
Exception-->    ResultWrapper res = fut.get();
                if (res != null) {
                    results.add(res);
                }
            }
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }

Если 2-й while убрать, то код отрабатывает нормально.
Почему так происходит? И как лучше реализовать неблокирующую проверку окончания работы callable потоков?

Ответы

▲ 1Принят

Решено. Эксепшен был связан с выходом за границы массива в callable потоке.