如何使用的invokeAll()让所有的线程池做自己的任务 [英] how to use invokeAll() to let all thread pool do their task

查看:569
本文介绍了如何使用的invokeAll()让所有的线程池做自己的任务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

    ExecutorService pool=Executors.newFixedThreadPool(7);
        List<Future<Hotel>> future=new ArrayList<Future<Hotel>>();
        List<Callable<Hotel>> callList = new ArrayList<Callable<Hotel>>();

        for(int i=0;i<=diff;i++){

            String str="2013-"+(liDates.get(i).get(Calendar.MONTH)+1)+"-"+liDates.get(i).get(Calendar.DATE);

            callList.add(new HotelCheapestFare(str));

        }       
     future=pool.invokeAll(callList);
for(int i=0;i<=future.size();i++){

        System.out.println("name is:"+future.get(i).get().getName());
    }

现在我想池中获取for循环,但是当我的for循环运行此程序,获取之前的invokeAll执行并抛出异常之前,所有的invokeAll任务。

now i want pool to invokeAll all the task before getting to the for loop but when i run this program for loop gets executed before that invokeAll and throws exception.

推荐答案

方式的的ExecutorService 工作原理是,当你调用的invokeAll 它会等待所有任务完成:

The way an ExecutorService works is that when you call invokeAll it waits for all tasks to complete:

执行给定的任务,返回的期货持有的名单
  状态和结果当所有完成。的Future.isDone()是对每个真
  返回列表的元素。 注意,一个完成的任务可以有
  终止正常地或通过抛出异常
。结果
  如果给定的集合被修改,这个方法是不确定的
  此操作正在进行。 <一href=\"http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ExecutorService.html#invokeAll%28java.util.Collection%29\">1(emphasis加)

Executes the given tasks, returning a list of Futures holding their status and results when all complete. Future.isDone() is true for each element of the returned list. Note that a completed task could have terminated either normally or by throwing an exception. The results of this method are undefined if the given collection is modified while this operation is in progress.1(emphasis added)

这是什么意思是,你的任务都做,但有些人可能会抛出异常。这个例外是未来的一部分 - 调用 GET 会导致异常重新抛出包裹在一个为ExecutionException

What that means is that your tasks are all done but some may have thrown an exception. This exception is part of the Future - calling get causes the exception to be rethrown wrapped in an ExecutionException.

从你stacktrack

From you stacktrack

java.util.concurrent.ExecutionException: java.lang.NullPointerException at
java.util.concurrent.FutureTask$Sync.innerGet(Unknown Source) at
java.util.concurrent.FutureTask.get(Unknown Source) at 
                                ^^^ <-- from get

您可以看到,这是真实的情况。你的任务之一失败与NPE。在的ExecutorService 捕捉到的异常,并通过抛出告诉你一个关于它的为ExecutionException 当你调用的Future.get

You can see that this is indeed the case. One of your tasks has failed with an NPE. The ExecutorService caught the exception and is telling you about it by throwing an ExecutionException when you call Future.get.

现在,如果你想利用任务的,因为他们完成的你需要一个 ExecutorCompletionService 。这作为一个的BlockingQueue ,让您轮询的任务,当他们完成。

Now, if you want to take tasks as they complete you need an ExecutorCompletionService. This acts as a BlockingQueue that will allow you to poll for tasks as and when they finish.

public static void main(String[] args) throws Exception {
    final ExecutorService executorService = Executors.newFixedThreadPool(10);
    final ExecutorCompletionService<String> completionService = new ExecutorCompletionService<>(executorService);
    executorService.submit(new Runnable() {
        @Override
        public void run() {
            for (int i = 0; i < 100; ++i) {
                try {
                    final Future<String> myValue = completionService.take();
                    //do stuff with the Future
                    final String result = myValue.get();
                    System.out.println(result);
                } catch (InterruptedException ex) {
                    return;
                } catch (ExecutionException ex) {
                    System.err.println("TASK FAILED");
                }
            }
        }
    });
    for (int i = 0; i < 100; ++i) {
        completionService.submit(new Callable<String>() {
            @Override
            public String call() throws Exception {
                if (Math.random() > 0.5) {
                    throw new RuntimeException("FAILED");
                }
                return "SUCCESS";
            }
        });
    }
    executorService.shutdown();
}

在这个例子中我有一个调用一个任务 ExecutorCompletionService 这得到未来能够像它们变得可用,然后我提交任务的 ExecutorCompletionService

In this example I have one task that calls take on the ExecutorCompletionService which gets the Futures as they become available and then I submit tasks to the ExecutorCompletionService.

这将允许你只要它未能得到失败的任务,而不必等待所有的任务,要么一起成功的失败。

This will allow you to get the failed task as soon as it fails rather than having to wait for all the tasks to either fail of succeed together.

唯一复杂的是,它是很难说的轮询线程,所有的任务都做了因为一切现在是异步的。在这种情况下我已经使用了100个任务将被提交以便它只需要轮询100倍知识。一个更普遍的方法是收集未来■从提交方法以及然后遍历他们看到如果一切都完成了。

The only complication is that it is difficult to tell the polling thread that all the tasks are done as everything is now asynchronous. In this instance I have used the knowledge that 100 tasks will be submitted so that it only need to poll 100 times. A more general way would be to collect the Futures from the submit method as well and then loop over them to see if everything is completed.

这篇关于如何使用的invokeAll()让所有的线程池做自己的任务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆