重温 GWT 客户端多线程

GWT client side multithreading revisited

我正在将一个 swing 应用程序转换为 GWT,它大量使用了多线程。该代码在后台运行连续的数值模拟,并以图形方式显示每一帧的结果。模拟需要知道每次计算经过了多少 real 时间。

摇摆

Thread calculate = new Thread(new Runnable(){
  // run calculation cycles every 10 ms 
  // (or as fast as possible)
  long prevT=System.currentTimeMillis();
  while(!isFinished){
    long currT = System.currentTimeMillis(),
         dt    = currT-prevT;
    if(dt<10)      Thread.sleep(5);
    else{
      simulate(dt);  
      prevT = currT;
    }
  }
}
// Update UI every 60 ms
java.awt.Timer timer = new Timer(60, new ActionListener(){public void actionPerformed(ActionEvent e){
  results = getCurrentSimState();
  uiPanel.render(results);
}});

此外,还有来自用户的事件驱动代码可以更改模拟器状态。

在 GWT 中实现它的最佳方法是什么?大多数以前的多线程问题主要与异步客户端-服务器工作有关。我看到了这个问题 Threading in GWT (Client),我想知道 Scheduler 是否合适:

GWT

void onLoad(){
  AnimationScheduler.get().requestAnimationFrame(callback, uiElement);
}
AnimationCallback cb = new AnimationCallback(){public void execute(double t){
  results = getCurrentSimState();
  render(results, uiElement);
  AnimationScheduler.get().requestAnimationFrame(callback, uiElement);
}};
double prevT=Duration.currentTimeMillis();
Scheduler.get().scheduleIncremental(new RepeatingCommand(){ public void execute() {
  double currT = Duration.currentTimeMillis(),
         dt    = currT-prevT;
  if(dt>30){
    calculate(dt);
    prevT = currT;
  }
  return isFinished;
}});

由于我是 GWT 的新手,我真的很想知道

  1. 这个设计可行吗?从线程设计到事件驱动设计是非常混乱的。
  2. 我不知道哪一个可能 "ticking" 更快。这两件事中哪一件优先? RepeatingCommand中的计算,还是AnimationScheduler中的GUI更新?
  3. 这个设计有什么重要的注意事项吗?我不希望页面被锁定!我任意选择了对两个线程使用不同的调度方式——这样正确吗?如果是,为什么?
  4. 10 毫秒可能太快了,但是有没有办法猜测合理的计算速率是多少?模拟器更新得越快,它就越准确。 (是RK4求解的刚性偏微分方程组!)

您可能需要考虑使用 Web Worker 进行真正的后台处理,而不是 "simulating" 使用 Scheduler 的多线程。

请注意,使用调度程序中的增量命令,您必须在工作完成时 return "false",或者在需要继续时 "true"。此命令仅在您可以将计算分成小块,然后将控制权交还给 JavaScript 可以执行用户操作的块之间时才有效。

如果您不能将工作分成小块,只有在每个计算周期花费的时间少于计算间隔的时间时,使用调度程序的方法才会起作用,从而给 JavaScript 一个对用户做出反应的机会activity计算之间。