繁体   English   中英

Java,如何将对象从工作线程传回主线程?

[英]In Java, how to pass the objects back to Main thread from worker threads?

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]);

为什么不使用CallableExecutorService

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

一种解决方法是在WorkerThread使用回调:

class WorkerThread extends Thread {
    ICallback callback;
    ...

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

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

}

您的调用类将在其中实现addResult并将其添加到result数组。

@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[][]并将Result[0]传递到可以用结果对象更新的子线程。 (轻巧的支架)。

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

主线程将需要等待工作线程完成才能获取结果。 一种方法是让主线程在尝试读取结果之前等待每个工作线程终止。 线程在其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 []数组中。 作为一种可能性,您可以通过在每个工作线程中传递数组和索引,并让工作线程在终止之前分配结果来实现。

一些典型的解决方案是:

  • 将结果保存在辅助线程的实例中(可以是RunnableThread )。 这类似于使用Future接口。
  • 使用构造工作线程的BlockingQueue ,可以将其放入结果中。
  • 只需使用ExecutorServiceCallable接口即可获取一个Future ,可以要求它提供结果。

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

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

我认为我有一个更好的解决方案,为什么不让工作线程将结果传递给linkedListBlockingQueue,完成后传递给他们,而您的主函数则从队列中选择结果

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
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM