【问题标题】:Get returning value of a thread获取线程的返回值
【发布时间】:2013-12-02 11:19:25
【问题描述】:

我在 Java 中定义了以下任务和线程:

private class FinderTask extends Task<mytype>{
   public FinderTask(){
      ...
   };

   @Override
   protected mytype call() throws Exception {

      mytype t = new mytype();
      ...
      return t;
   }
}

开始线程

MainController.FinderTask task = new myClass.FinderTask();
task.runningProperty().addListener(new ChangeListener<Boolean>() {
   @Override 
   public void changed(ObservableValue<? extends Boolean> ov, Boolean wasRunning, Boolean isRunning) {
            if (!isRunning) {

                System.out.println("task finished");
            }
          }
        });

final Thread thread = new Thread(task , "finder");
thread.setDaemon(true);
thread.start();

如何获取调用函数的返回值?

【问题讨论】:

  • 没有称为Task 的标准Java 类。请分享此类的代码或更正您的代码示例。你的意思是FutureTask?另请注意,Java 类名真的应该是 CamelCase 否则你会开始混淆人们。
  • 我认为您在这里混淆了很多概念。即 Callable、Future 和 Observer 模式。
  • @Duncan,我正在使用 javafx 并发任务docs.oracle.com/javafx/2/api/javafx/concurrent/Task.html

标签: java multithreading javafx-2 javafx task


【解决方案1】:

你可以使用 task.getValue();这将在任务状态转换为 SUCCEEDED 之前设置;因此它将在侦听器的 if 子句中起作用(您需要使您的任务最终完成)。

值也是一个可观察的属性,所以你也可以这样做

task.valueProperty().addListener(new ChangeListener<Task>() {
  @Override
  public void changed(ObservableValue<? extends mytype> obs, mytype oldValue, mytype newValue) {
    if (newValue != null) {
      System.out.println("Result of task "+newValue);
    }
  }
});

【讨论】:

    【解决方案2】:

    如果你像这样运行它,即普通线程,请参阅FutureTask (ref) 继承的 get() 方法。使用 here 中描述的 Service 类 (ref) 或 Java 的标准并发(例如执行程序)可能更合适。

    【讨论】:

      【解决方案3】:

      您可以让FinderTaskcall 方法记录它需要在本地实例变量中返回的信息——为该变量添加一个getter 将使结果可访问。

      或者,您可以创建一个Queue 并将其传递给FinderTask 构造。当调用 call 方法时,只需将结果推送到队列中。然后,您可以保持队列的另一端并听取结果。如果您使用BlockingQueue,则非常有效,因为您可以使用阻塞直到结果可用的监听方法。

      【讨论】:

      • 请注意,如果您这样做,本地实例变量将从执行任务调用方法的后台线程更新。这将使其不适合更新 UI,只能从 JavaFX 应用程序线程更新。
      • @James_D - 当然可以在您喜欢的任何线程中从对象中读取结果。在这里,我建议将其存储在对象或阻塞队列中 - 您可以从对象/队列中读取任何您喜欢的线程。
      • (抱歉回复延迟。)不,这不能保证有效;至少不是不使用一些同步原语。 Java 语言规范允许 JVM 进行各种优化,以防止对一个线程中的变量所做的更新在另一个线程中可见,除非使用了同步。 Josh Bloch 的“Effective Java”和 Brian Goetz 的“Java Concurrency in Practice”是这方面的极好资源。将对象传递给 BlockingQueue 将起作用,因为 BlockingQueue 实现负责低级同步。
      • @James_D - 我会创建变量 volatile 但假设 OP 会知道这一点。
      • 当然可以。鉴于对 Java 中的线程存在大量误解,这可能是一个轻率的假设(无意冒犯 OP;只是关于有多少程序员没有做到这一点的一般性声明)。 Task 和 Service 类提供了在 FX 应用程序线程上工作的直接功能,以避免应用程序程序员不得不使用同步和易失的原语。
      猜你喜欢
      • 2011-10-29
      • 2019-04-22
      • 2020-11-09
      • 1970-01-01
      • 1970-01-01
      • 2011-10-17
      • 2018-04-15
      相关资源
      最近更新 更多