2014-02-11 2 views
4

В этом примере есть экземпляр класса Input и класса Result. Вводный экземпляр заполняется в GUI-Thread, здесь JavaFX Application Thread. После нажатия кнопки этот экземпляр ввода используется в рабочем потоке. Затем рабочий поток создает экземпляр класса Result и заполняет его некоторыми значениями после того, как эта Platform.runLater вызывается для обновления GUI.видимость данных во время (/ после) выполнения потока

Мой первый вопрос: Гарантировано ли, что рабочий поток видит значения экземпляра ввода?

Я бы сказал, да, из-за следующего: JLS 17.4.5. Случается перед заказом, говорит: Вызов start() в потоке происходит - перед любыми действиями в начатом потоке.

Таким образом, с моей точки зрения все, что сделано в потоке JavaFX до, запускается при запуске .

Мой второй вопрос: Гарантировано ли, что в приложении JavaFX Application Thread видятся значения экземпляра результата?

Я думаю, да, но я не уверен. Будет ли Platform.runLater гарантировать это? Как?

package javafxconcurrency; 

import javafx.application.Application; 
import javafx.application.Platform; 
import javafx.concurrent.Task; 
import javafx.event.ActionEvent; 
import javafx.event.EventHandler; 
import javafx.scene.Scene; 
import javafx.scene.control.Button; 
import javafx.scene.layout.StackPane; 
import javafx.stage.Stage; 

public class JavaFxConcurrency extends Application { 

    private Input input; 

    @Override 
    public void start(Stage primaryStage) { 
     input = new Input(); 
     input.setId(1); 
     input.setName("Jack"); 

     Button btn = new Button(); 
     btn.setText("Start a thread"); 
     btn.setOnAction(new EventHandler<ActionEvent>() { 

      @Override 
      public void handle(ActionEvent event) { 
       Task<Result> task = new Task() { 

        @Override 
        protected Object call() throws Exception { 
         final Result result = queryDB(input); 
         Platform.runLater(new Runnable() { 

          @Override 
          public void run() { 
           updateGUI(result); 
          } 

         }); 
         return result; 
        } 

        private Result queryDB(Input input) { 
         try { 
          Thread.sleep(3000); 
          Result result = new Result(); 
          result.setId(System.currentTimeMillis()); 
          result.setName(input.getName()); 
          return result; 
         } catch (InterruptedException ex) { 
          throw new RuntimeException(ex); 
         } 
        } 

       }; 
       Thread workerThread = new Thread(task); 
       workerThread.setDaemon(true); 
       workerThread.start(); 
      } 

     }); 

     StackPane root = new StackPane(); 
     root.getChildren().add(btn); 

     Scene scene = new Scene(root, 300, 250); 

     primaryStage.setTitle("Visibilty"); 
     primaryStage.setScene(scene); 
     primaryStage.show(); 
    } 

    private void updateGUI(Result result) { 
     System.out.println("result" + result); 
    } 

    public static void main(String[] args) { 
     launch(args); 
    } 

    private static class Input { 

     private long id; 

     private String name; 

     public void setId(long id) { 
      this.id = id; 
     } 

     public long getId() { 
      return id; 
     } 

     public void setName(String name) { 
      this.name = name; 
     } 

     public String getName() { 
      return name; 
     } 

    } 

    private static class Result { 

     private long id; 

     private String name; 

     public void setId(long id) { 
      this.id = id; 
     } 

     public long getId() { 
      return id; 
     } 

     public void setName(String name) { 
      this.name = name; 
     } 

     public String getName() { 
      return name; 
     } 

     @Override 
     public String toString() { 
      return "Result{" + "id=" + id + ", name=" + name + '}'; 
     } 

    } 

} 

ответ

4

ли он гарантировал, что рабочий поток видит значение экземпляра ввода?

Да: Thread#start создает происшествие до отношений. Так у вас есть:

  • input.setName("Jack"); происходит, перед тем workerThread.start();, потому что они оба на FX тему, так что вы получите гарантии программы порядка
  • workerThread.start(); случается, перед тем result.setName(input.getName()); по той причине, вы упоминались (все действия до нитки запускаются произойдут до каких-либо действий выполняются в этом потоке)

Это гарантировано, что JavaFX Application Thread видит значение экземпляра результата?

Да, Platform.runLater также обеспечивает бывает, до отношений, как намекают the javadoc: «Этот метод [...] может быть вызван из любого потока». Если вы не уверены, можете взглянуть на the code, и вы увидите, что есть несколько точек синхронизации.

Без этой гарантии было бы невозможно связаться с компонентами JavaFX без ручной синхронизации всех.

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