控制另一个线程的倒计时

时间:2012-11-30 21:42:45

标签: java concurrency javafx-2

我想在我的JavaFX应用程序中实现一个计数器。只需通过Button:

控制行为
  1. 当用户先点击按钮时,倒计时开始倒计时10,9,8,...,0
  2. 当用户在倒计时期间点击按钮时,倒计时应取消
  3. 2.用户应该能够从10开始再次运行倒计时
  4. 在倒计时期间,处理了一些繁重的数学计算(在我的应用程序音频分析中)。

    如果我以正确的方式做到这一点,你能看看我的源代码吗?特别应该在Platform.runLaterCountdownController上执行CountdownView内容,我可以使用简单的Java Thread,还是应该使用JavaFX Service / Task课程?欢迎任何建议。

    该申请分为3个部分:

    1. CountdownTest:创建舞台并启动JavaFX)
    2. CountdownView:singleton,包含一个简单的Button,将按钮事件传递给CountdownController
    3. CountdownController:单身,开始新的Thread。在执行倒计时的Thread内,CountdownView为updatet以显示新的倒计时状态,并处理了一些数学内容。
    4. CountdownTest.java

      package org.example;
      
      import javafx.application.Application;
      import javafx.scene.Group;
      import javafx.scene.Scene;
      import javafx.stage.Stage;
      
      public class CountdownTest extends Application {
          @Override
          public void start(Stage primaryStage) throws Exception {
              final Group root = new Group();
              final Scene scene = new Scene(root);
              root.getChildren().setAll(CountdownView.getInstance());
              primaryStage.setScene(scene);
              primaryStage.show();
          }
      
          @Override
          public void stop() throws Exception {
              super.stop();
              CountdownController.getInstance().stop();
          }
      
          public static void main(String[] args) {
              launch(args);
          }
      }
      

      CountdownView.java

      package org.example;
      
      import javafx.event.EventHandler;
      import javafx.scene.Group;
      import javafx.scene.control.Button;
      import javafx.scene.control.Tooltip;
      import javafx.scene.input.MouseEvent;
      
      public final class CountdownView extends Group {
          private static final CountdownView instance = new CountdownView();
      
          private Button start;
      
          private CountdownView() {
              start = new Button("Start");
              start.setTooltip(new Tooltip("click to start countdown"));
              start.setOnMouseClicked(new EventHandler<MouseEvent>() {
                  @Override
                  public void handle(MouseEvent event) {
                      CountdownController.getInstance().onStartClick();
                  }
              });
      
              this.getChildren().setAll(start);
          }
      
          public void startCountdown() {
              System.out.println("startCountdown");
              start.setTooltip(new Tooltip("click to stop countdown"));
          }
      
          public void setCountdown(final int countdown) {
              System.out.println("setCountdown " + countdown);
              start.setText(String.valueOf(countdown));
          }
      
          public void reset() {
              System.out.println("reset");
              start.setText("Start");
              start.setTooltip(new Tooltip("click to start countdown"));
          }
      
          public static CountdownView getInstance() {
              return instance;
          }
      }
      

      CountdownController.java

      package org.example;
      
      import javafx.application.Platform;
      
      public final class CountdownController {
          private static final CountdownController instance = new CountdownController();
      
          private Thread countdownThread;
          private volatile boolean running = false;
      
          public void onStartClick() {
              if (!running) {
                  countdownThread = new Thread(new Runnable() {
                      @Override
                      public void run() {
                          running = true;
                          int countdown = 10;
                          Platform.runLater(new Runnable() {
                              @Override
                              public void run() {
                                  CountdownView.getInstance().startCountdown();
                                  CountdownView.getInstance().setCountdown(10);
                              }
                          });
                          final long start = System.currentTimeMillis();
                          int lastCountdown = countdown;
                          while (!Thread.interrupted() && countdown > 0) {
                              countdown = (int) (10 - (System.currentTimeMillis() - start) / 1000);
                              if (countdown != lastCountdown) {
                                  lastCountdown = countdown;
                                  final int currentCountdown = countdown;
                                  Platform.runLater(new Runnable() {
                                      @Override
                                      public void run() {
                                          CountdownView.getInstance().setCountdown(
                                                  currentCountdown);
                                      }
                                  });
                              }
      
                              // Do some heavy computing stuff
                              for (int i = 0; i < 10000000; i++) {
                                  Math.sin(Math.random());
                              }
                          }
                          running = false;
                          Platform.runLater(new Runnable() {
                              @Override
                              public void run() {
                                  CountdownView.getInstance().reset();
                              }
                          });
                      }
                  });
                  countdownThread.start();
              } else {
                  countdownThread.interrupt();
              }
          }
      
          public void stop() {
              if (countdownThread != null) {
                  System.out.println("stop");
                  countdownThread.interrupt();
              }
          }
      
          public static CountdownController getInstance() {
              return instance;
          }
      }
      

1 个答案:

答案 0 :(得分:1)

不要过度出汗。任务和服务类只是在执行程序上构建的一些实用程序,如果你不需要他们提供的东西,那么它只是额外的工作。

我认为你使用控制器决定应该运行哪些线程是正确的,你的视图足以在组件和控制器之间进行路由消息。