在java中如何从线程中获取返回值?

时间:2013-08-15 22:49:38

标签: java multithreading return-value

以下代码编译但在运行时导致空指针异常。 我最好的猜测是outputInts对每个线程都不“可见”,因此无法写入。

public class myClass{

ArrayList<int> outputints

public void foo(int start, int end) {
    for (int i = start; i <= end; i++) {
          bar(i);
        }

private void bar(int i) {
    class OneShotTask implements Runnable {
        int i;
        OneShotTask(int j) {
            i = j;
        }
        @Override
        public void run() {
            try {
                    System.out.println(i);
                    outputints.add(i);      //null pointer exception caused here
                }
            } catch (Exception e) {
                System.out.println(e.toString());
            }

        }
    }
    Thread t = new Thread(new OneShotTask(j));
    t.start();
  }

 }

我已经读过我应该使用callable来实现这一点,但我不明白这是如何实现的。另外像java Runnable run() method returning a value这样的例子似乎暗示我可以运行一些线程,使用一个可调用的地方,我可能需要在一千个线程的区域。

我正在寻求帮助以使上述实施工作或外行人的条款指导如何通过可赎回来实现

2 个答案:

答案 0 :(得分:3)

Brian Goetz写了一本名为Java Concurrency in Practice的好书,深入介绍了这一点。您应该考虑使用完成服务,它是一种Executor。以下是示例java代码:

     void solve(Executor e, Collection<Callable<Result>> solvers)
         throws InterruptedException, ExecutionException {
           CompletionService<Result> ecs = new ExecutorCompletionService<Result>(e);
           for (Callable<Result> s : solvers)
             ecs.submit(s);
           int n = solvers.size();
           for (int i = 0; i < n; ++i) {
             Result r = ecs.take().get();
               if (r != null)
                 use(r);
 }
}

您可以使用take()方法从ExecutorCompletionService检索已完成的Futures。在FutureTask上调用get()方法来获取结果。这些类可以使用泛型进行参数化,以确保类型安全,并提高代码灵活性。

答案 1 :(得分:1)

ArrayList<Integer> outputints = new ArrayList<Integer>();

你的IDE应该保护你免受这种错误......