方法检查锁定,锁定释放后运行

时间:2018-06-06 07:37:46

标签: javafx locking runnable race-condition

我面临潜在的追逐错误。我使用javafx TableView来显示我的数据,并且我定期在外部接收一个调用我的更新功能的更新请求。我也有一些听众会做一些事情,比如处理mousedrag事件等等。我想做的是做这样的事情:

private void handleEvent(){
  TableView.setRowFactory(new Callback<TableView<MyModel>, TableRow<MyModel>>(){
    public TableRow<MyModel> call(TableView<MyModel> p) {
      final TableRow row = new TableRow();
      row.setOnDragDetected(new EventHandler<MouseEvent>(){
        public void handle(){
          //implement some kind of lock to prevent receiving data update
        }
      }
      row.setOnMouseDragExited(new EventHandler<MouseDragEvent>(){
        //release lock to accept update
      }
   }
}

//this method is being called externally periodically
public void updateModel(MyModel model){
  //this won't work because it will skip entirely if it's locked,
  //I want it to instead run later when lock is released
  if (!locked){
    this.model = model;
  }
}

我做了一个快速的解决方法,使用布尔来锁定和解锁,如updateModel方法所示,问题是它会丢失一些更新的数据,因为它被完全跳过..相反,我希望它在以后锁定释放时运行..如何实现这种锁机制并运行以后的功能?

编辑:为什么我怀疑这是因为我的听众正在操纵并获取表数据..虽然数据不断更新,但我不确定这是否会导致我的表中断。

1 个答案:

答案 0 :(得分:2)

只需编写一些逻辑,收集您在锁定状态下尝试执行的所有操作,并在解锁时执行。

以下代码假定您使用{ read: true, create: true, delete: false, update: false } 或类似的代码,使更新在应用程序线程上运行。

Platform.runLater

如果上次更新总是覆盖以前更新的所有数据,只需保留一个public class UpdateSynchronizer { private final List<Runnable> pendingUpdates = new ArrayList<>(); private boolean locked = false; public void lock() { if (locked) { throw new IllegalStateException("double lock"); } else { locked = true; } } public void runUpdate(Runnable updater) { if (updater == null) { throw new IllegalArgumentException(); } if (locked) { pendingUpdates.add(updater); } else { updater.run(); } } public void unlock() { for (Runnable r : pendingUpdates) { try { r.run(); } catch(Exception ex) { ex.printStackTrace(); // print but ignore } } pendingUpdates.clear(); locked = false; } } 而不是列表,就会更有效。

Runnable