方法检查锁,锁释放后运行
Method checks for lock, runs after lock released
我面临潜在的追逐错误。我使用 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 方法所示,使用布尔值来锁定和解锁,问题是它会丢失一些更新的数据,因为它被完全跳过了。相反,我希望它 运行 稍后释放锁时.. 我如何实现这种锁机制和 运行 以后的功能?
编辑:为什么我怀疑这是因为我的听众正在操纵和获取 table 数据..虽然数据不断更新,但我不确定这是否导致我的 table休息。
只需编写一些逻辑,收集您在锁定状态下尝试执行的所有操作,并在解锁时执行。
以下代码假定您正在使用 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
而不是一个列表会更高效。
private final UpdateSynchronizer synchronizer = new UpdateSynchronizer();
// why did all the keywords start with uppercase letters (compile time error)
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(){
synchronizer.lock();
//implement some kind of lock to prevent receiving data update
}
}
row.setOnMouseDragExited(new EventHandler<MouseDragEvent>(){
//release lock to accept update
synchronizer.unlock();
}
}
}
//this method is being called externally periodically
public void updateModel(myModel model){
synchronizer.runUpdate(() -> {
// this is just an assignment and won't have any side effects
// updates to the scene may only happen, if the model is accessed in some event handler or animation
this.model = model;
});
}
我面临潜在的追逐错误。我使用 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 方法所示,使用布尔值来锁定和解锁,问题是它会丢失一些更新的数据,因为它被完全跳过了。相反,我希望它 运行 稍后释放锁时.. 我如何实现这种锁机制和 运行 以后的功能?
编辑:为什么我怀疑这是因为我的听众正在操纵和获取 table 数据..虽然数据不断更新,但我不确定这是否导致我的 table休息。
只需编写一些逻辑,收集您在锁定状态下尝试执行的所有操作,并在解锁时执行。
以下代码假定您正在使用 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
而不是一个列表会更高效。
private final UpdateSynchronizer synchronizer = new UpdateSynchronizer();
// why did all the keywords start with uppercase letters (compile time error)
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(){
synchronizer.lock();
//implement some kind of lock to prevent receiving data update
}
}
row.setOnMouseDragExited(new EventHandler<MouseDragEvent>(){
//release lock to accept update
synchronizer.unlock();
}
}
}
//this method is being called externally periodically
public void updateModel(myModel model){
synchronizer.runUpdate(() -> {
// this is just an assignment and won't have any side effects
// updates to the scene may only happen, if the model is accessed in some event handler or animation
this.model = model;
});
}