[java] JavaFX의 Platform.runLater 및 Task

나는 이것에 대해 약간의 연구를 해왔지만 여전히 가장 적게 말하는 것은 매우 혼란 스럽습니다.

누구든지 언제 사용 Task하고 언제 사용 Platform.runLater(Runnable);하는지에 대한 구체적인 예를 줄 수 있습니까 ? 차이점은 정확히 무엇입니까? 이들 중 언제 사용 하는가에 대한 황금률이 ​​있습니까?

또한 내가 틀렸지 만이 두 “객체”가 GUI의 주 스레드 내부에 다른 스레드를 만드는 방법이 아닌 경우에도 수정하십시오 (GUI 업데이트에 사용됨)?



답변

사용하여 Platform.runLater(...)빠르고 간단하게 작업하고 Task복잡하고 큰 작업.

예 : Platform.runLater(...)긴 계산에 사용할 수없는 이유 (아래 참조에서 발췌).

문제 : 0에서 1 백만까지 계산되는 백그라운드 스레드와 UI의 업데이트 진행률 표시 줄.

다음을 사용하는 코드 Platform.runLater(...):

final ProgressBar bar = new ProgressBar();
new Thread(new Runnable() {
    @Override public void run() {
    for (int i = 1; i <= 1000000; i++) {
        final int counter = i;
        Platform.runLater(new Runnable() {
            @Override public void run() {
                bar.setProgress(counter / 1000000.0);
            }
        });
    }
}).start();

이것은 끔찍한 코드 덩어리이며, 자연에 반하는 범죄입니다 (일반적으로 프로그래밍). 첫째,이 Runnables의 이중 중첩을 보는 것만으로도 뇌 세포를 잃게됩니다. 둘째, 작은 Runnables로 이벤트 대기열을 휩쓸 것입니다. 실제로는 백만 개입니다. 분명히, 우리는 UI와 다시 통신하는 백그라운드 워커를 더 쉽게 작성하기 위해 약간의 API가 필요했습니다.

Task를 사용하는 코드 :

Task task = new Task<Void>() {
    @Override public Void call() {
        static final int max = 1000000;
        for (int i = 1; i <= max; i++) {
            updateProgress(i, max);
        }
        return null;
    }
};

ProgressBar bar = new ProgressBar();
bar.progressProperty().bind(task.progressProperty());
new Thread(task).start();

이전 코드에 나타난 결함이 없습니다.

참조 :
JavaFX 2.0의 작업자 스레딩


답변

  • Platform.runLater: GUI가 아닌 스레드에서 GUI 구성 요소를 업데이트해야하는 경우이를 사용하여 업데이트를 대기열에 넣을 수 있으며 가능한 한 빨리 GUI 스레드에서 처리합니다.
  • TaskWorkerGUI 스레드 외부에서 긴 작업을 실행해야하지만 (애플리케이션 동결을 방지하기 위해) 일부 단계에서 여전히 GUI와 상호 작용해야 할 때 사용되는 인터페이스를 구현합니다 .

Swing에 대해 잘 알고 있다면 전자는 SwingUtilities.invokeLater의 개념과 같고 후자는의 개념과 같습니다 SwingWorker.

Taskjavadoc은 사용 방법을 명확히해야하는 많은 예제를 제공합니다. 동시성대한 자습서를 참조 할 수도 있습니다 .


답변

이제 람다 버전으로 변경할 수 있습니다.

@Override
public void actionPerformed(ActionEvent e) {
    Platform.runLater(() -> {
        try {
            //an event with a button maybe
            System.out.println("button is clicked");
        } catch (IOException | COSVisitorException ex) {
            Exceptions.printStackTrace(ex);
        }
    });
}


답변

명시 적 Platform.runLater ()를 사용하는 한 가지 이유는 UI의 속성을 서비스 (결과) 속성에 바인딩했기 때문일 수 있습니다. 따라서 바인딩 된 서비스 속성을 업데이트하는 경우 runLater ()를 통해이를 수행해야합니다.

JavaFX 애플리케이션 스레드라고도하는 UI 스레드에서 :

...
listView.itemsProperty().bind(myListService.resultProperty());
...

서비스 구현 (백그라운드 작업자) :

...
Platform.runLater(() -> result.add("Element " + finalI));
...


답변