2

在Java中,如何将对象从工作线程传回主线程?以以下代码为例:

  main(String[] args) {

    String[] inputs;
    Result[] results;
    Thread[] workers = new WorkerThread[numThreads];

    for (int i = 0; i < numThreads; i++) {
        workers[i] = new WorkerThread(i, inputs[i], results[i]);
        workers[i].start();
    } 

    ....
  }
  ....

class WorkerThread extends Thread {
    String input;
    int name;
    Result result;

    WorkerThread(int name, String input, Result result) {
        super(name+"");
        this.name = name;
        this.input = input;
        this.result = result;
    }

    public void run() {
        result  = Processor.process(input);
    }
}

怎么传result回给mainresults[i]

this传递给WorkerThread,怎么样

workers[i] = new WorkerThread(i, inputs[i], results[i], this);

这样它就可以

mainThread.reults[i] = Processor.process(inputs[i]);
4

6 回答 6

5

为什么不使用Callables和 an ExecutorService

main(String[] args) {

  String[] inputs;
  Future<Result>[] results;

  for (int i = 0; i < inputs.length; i++) {
    results[i] = executor.submit(new Worker(inputs[i]);
  } 
  for (int i = 0; i < inputs.length; i++) {
    Result r = results[i].get();
    // do something with the result
  }
}
于 2012-09-01T00:23:46.363 回答
1

@Thilo 和 @Erickson 的答案是最好的。现有的 API 可以简单可靠地执行此类操作。

但是,如果您想坚持当前的手动操作方法,那么对您的代码进行以下更改可能就足够了:

for (int i = 0; i < numThreads; i++) {
    results[i] = new Result();
    ...
    workers[i] = new WorkerThread(i, inputs[i], results[i]);
    workers[i].start();
}

...

public void run() {
    Result tmp = Processor.process(input);
    this.result.updateFrom(tmp);
    // ... where the updateFrom method copies the state of tmp into
    // the Result object that was passed from the main thread.
}

另一种方法是Result[]在主程序中替换为Result[][]a 并将其传递Result[0]给可以使用结果对象更新的子线程。(一个轻量级的持有人)。

但是,当您在低级别实现此功能时,我们有一个重要的问题是主线程需要在尝试检索结果之前在所有子线程上调用 Thread.join。如果不这样做,主线程可能会偶尔在 Result 对象中看到陈旧的值。这join还确保main线程在相应的子线程完成之前不会尝试访问 Result。

于 2012-09-01T00:43:36.780 回答
0

主线程需要等待工作线程完成才能获得结果。一种方法是让主线程在尝试读取结果之前等待每个工作线程终止。线程在其 run() 方法完成时终止。

例如:

for (int i = 0; i < workers.length; i++) {
  worker.join(); // wait for worker thread to terminate
  Result result = results[i]; // get the worker thread's result
  // process the result here...
}

您仍然必须安排工作线程的结果以某种方式插入到 result[] 数组中。作为一种可能性,您可以通过将数组和索引传递给每个工作线程并让工作线程在终止之前分配结果来做到这一点。

于 2012-09-01T00:22:33.010 回答
0

一些典型的解决方案是:

  • 将结果保存在工作线程的实例中(无论是它Runnable还是Thread)。这类似于Future接口的使用。
  • 使用BlockingQueue构建工作线程的 a,它们可以将结果放入其中。
  • 简单地使用ExecutorServiceCallable接口来获得一个Future可以被询问的结果。
于 2012-09-01T00:28:40.690 回答
0

看起来您的目标是并行执行计算,然后一旦所有结果都可用于主线程,它就可以继续并使用它们。

如果是这种情况,请将您的并行计算实现为一个Callable而不是一个线程。将此任务集合传递invokeAll()ExecutorService. 此方法将阻塞,直到所有任务都完成,然后您的主线程才能继续。

于 2012-09-01T00:39:05.507 回答
0

I think I have a better solution, why don't you make your worker threads pass the result into a linkedListBlockingQueue, which is passed to them, after they are done, and your main function picks the results up from the queue like this

while(true){linkedListBlockingQueue.take(); 
    //todo: fil in the task you want it to do
    //if a specific kind of object is returned/countdownlatch is finished exit
}
于 2012-09-01T09:38:05.343 回答