主线程必须等待,直到从另一个阶段获取输入

时间:2016-08-28 11:56:54

标签: multithreading task javafx-8 worker

我有以下情况:

  1. 向用户显示登录屏幕

  2. 用户将尝试登录

  3. javafx任务将开始与服务器通信。

  4. 当通信工作在后面时,将向用户显示一个不确定的进度条(从主线程调用)。

  5. 如果登录凭据正确,则会向用户移动设备发送OTP消息。

  6. 将显示OTP对话框(javafx阶段),用户应输入收到的OTP(主线程应等到获得此OTP然后才能继续处理)。

  7. 不幸的是,我遇到了很多问题,如下所示:

    1 - 当前OTP对话框从后台通信线程通过Platform.runLater调用,但主线程继续运行而不等待OTP。

    我该如何完成这项任务?????

2 个答案:

答案 0 :(得分:0)

如果你运行一个新线程与服务器通信,你可以简单地让主线程等待,直到这个线程结束Thead.join()

  

join方法允许一个线程等待另一个线程的完成。   如果t是其当前正在执行其线程的Thread对象,则

t.join();
     

导致当前线程暂停执行,直到t的线程终止。连接过载允许程序员指定等待期。但是,与sleep一样,join依赖于操作系统进行计时,因此您不应该假设连接将等待您指定的时间。

     

与sleep一样,join通过退出InterruptedException来响应中断。

如果你有一个线程池(或者有其他理由不完成你的后台thead),那么我们谈论线程同步。请查看PhaserCyclicBarrier

  

一种同步辅助工具,允许一组线程全部等待彼此到达公共障碍点。 CyclicBarriers在涉及固定大小的线程方的程序中很有用,这些线程必须偶尔等待彼此。屏障称为循环,因为它可以在等待线程释放后重新使用。

 class Solver {
   final int N;
   final float[][] data;
   final CyclicBarrier barrier;

   class Worker implements Runnable {
     int myRow;
     Worker(int row) { myRow = row; }
     public void run() {
       while (!done()) {
         processRow(myRow);

         try {
           barrier.await();
         } catch (InterruptedException ex) {
           return;
         } catch (BrokenBarrierException ex) {
           return;
         }
       }
     }
   }

   public Solver(float[][] matrix) {
     data = matrix;
     N = matrix.length;
     barrier = new CyclicBarrier(N,
                                 new Runnable() {
                                   public void run() {
                                     mergeRows(...);
                                   }
                                 });
     for (int i = 0; i < N; ++i)
       new Thread(new Worker(i)).start();

     waitUntilDone();
   }
 }

答案 1 :(得分:0)

您的应用程序需要编写大量代码,因此这里将提供一个主要使用单词的解决方案。

  

~~&gt;使用JavaFX服务

JavaFX支持Service类。您必须创建一个扩展Service的类,如下所示:

public ServerWork extends Service<Boolean>{...}
关于如何使用服务的

Read this

这个类将有一个名为startService()的方法,它将启动CountDownLatch,因此调用此方法的主线程将冻结,直到Service完成。

class

......

private CountDownLatch countDown;


//Constructor
public ServerWork( ){


 //if service succeeded
 onSucceed(f->{ 
     .....
     done();
 };


//if Service failed 
  onFailed(f->{   
   ..... 
    done();
   };


//if Service cancelled 
   onCancelled(f->{
     .....
      done();
   };

}

/** Start the Service */
 public void startService ( ){

  //Service is not Running
  if(!isRunning()){

    countDown= new CountDownLatch(1);
    countDown.await();

    reset();
    start();

   }

 }

 /** Service has finished failed or not or cancelled */
 private void done( ){ 
   //unbind the progress bar or progress indicator here

   progressbar.progressProperty().unbind();

  //countDown so main thread is released
  countDown.countDown( );

}



//..@Override createTask() and update Service progress 
  

~~&GT;最后是用户界面

在您的舞台上,您将拥有ProgressIndicatorProgressBar,您将把它的进度属性绑定到服务的progressProperty,如下所示:

progressIndicator.progressProperty().bind(ServerWorkInstance().progressProperty();

要完全理解上面的内容,请阅读上面给出的链接并搜索一些教程。