2013-12-02 5 views
1

I, определенной в 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(); 

Как я могу получить возвращаемое значение функции вызова?

+1

Там нет стандартного класса Java называется 'Task'. Пожалуйста, поделитесь кодом этого класса или исправьте пример кода. Вы имели в виду ['FutureTask'] (http://docs.oracle.com/javase/7/docs/api/index.html?java/util/concurrent/FutureTask.html)? Также обратите внимание, что имена классов Java должны действительно быть «CamelCase», иначе вы начнете путать людей. –

+2

Я думаю, вы вводите в заблуждение множество концепций. А именно Callable, Future и шаблон Observer. – TwoThe

+1

@ Duncan, я использую совместную задачу javafx http://docs.oracle.com/javafx/2/api/javafx/concurrent/Task.html – Danilo

ответ

2

Вы можете просто использовать 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); 
    } 
    } 
}); 
0

Если вы запустите его так, то есть простой поток, см. Методы get(), унаследованные FutureTask (ref). Может быть более целесообразным использовать класс Service (ref), как описано here, или стандартный параллелизм Java (например, исполнители).

0

Вы можете сделать способ callFinderTask записать информацию, которую он должен вернуть в локальной переменной экземпляра - добавление геттера для этой переменной позволит получить результат.

В качестве альтернативы вы можете создать Queue и передать его на FinderTask по строительству. Когда вызывается метод call, просто вставляйте свой результат в очередь. Затем вы можете просто держать другой конец очереди и слушать результат. Очень эффективно, если вы используете BlockingQueue, потому что вы можете использовать метод прослушивания, который блокируется до тех пор, пока результат не будет доступен.

+0

Обратите внимание, что если вы сделаете это, переменная локального экземпляра будет обновлена ​​с фоновый поток, на котором выполняется метод вызова задачи. Это сделает его непригодным для обновления пользовательского интерфейса, который может быть обновлен только из приложения JavaFX Application Thread. –

+0

@James_D - Конечно, результат может быть считан из объекта в любом потоке, который вам нравится. Здесь я рекомендую либо хранить его в объекте, либо в очереди блокировки - вы можете читать из формы объекта/очереди любой поток, который вам нравится. – OldCurmudgeon

+0

(Извините за задержку в ответе.) Нет, это не гарантирует работу; по крайней мере, не используя некоторые примитивы синхронизации. Спецификация Java Language Spec позволяет JVM делать всевозможные оптимизации, которые могут препятствовать обновлению, сделанным переменной в одном потоке, видимым в другом потоке, если только не используется синхронизация. «Эффективная Java» Джоша Блоха и Брайан Гетц «Java Concurrency на практике» - отличные ресурсы для этого. Передача объекта в BlockingQueue будет работать, так как реализация BlockingQueue заботится о низкоуровневой синхронизации. –

Смежные вопросы