edt嵌入式确定性测试_CallSerially EDT和InvokeAndBlock(第2部分)

edt嵌入式确定性测试

edt嵌入式确定性测试

834427872
上一次我们讨论EDT时,我们介绍了一些基本概念,例如串行调用等。我们省略了两个更高级的主要概念。

调用并阻止

当我们用Java编写典型代码时,我们希望该代码按顺序排列:

doOperationA();
doOperationB();
doOperationC();

这正常工作良好,但在EDT上可能会出现问题,如果其中一项操作缓慢,则可能会减慢整个EDT(绘画,事件处理等)的速度。 通常我们可以将操作移到单独的线程中,例如:

doOperationA();
new Thread() {
    public void run() {
         doOperationB();
    }
}).start();
doOperationC();

不幸的是,这意味着操作C将与操作C并行发生,这可能是一个问题……例如,与其使用操作名称,不如使用一个“现实世界”示例:

updateUIToLoadingStatus();
readAndParseFile();
updateUIWithContentOfFile();

请注意,必须在EDT上执行第一个和最后一个操作,但是中间操作可能真的很慢!由于updateUIWithContentOfFile在执行新线程之前需要readAndParseFile是不够的。 我们的自动方法是执行以下操作:

updateUIToLoadingStatus();
new Thread() {
    public void run() {
          readAndParseFile();
          updateUIWithContentOfFile();
    }
}).start();

但是updateUIWithContentOfFile应该在EDT上执行,而不是在随机线程上执行。 所以正确的方法是这样的:

updateUIToLoadingStatus();
new Thread() {
    public void run() {
          readAndParseFile();
          Display.getInstance().callSerially(new Runnable() {
               public void run() {
                     updateUIWithContentOfFile();
               }
          });
    }
}).start();

这是完全合法的,并且可以合理地很好地工作,但是随着我们添加越来越多的功能,而这些功能仅是3种方法,就需要串行地链接起来,因此变得很复杂!

调用和阻止以独特的方式解决此问题,您可以使用以下方法获得几乎完全相同的行为:

updateUIToLoadingStatus();
Display.getInstance().invokeAndBlock(new Runnable() {
    public void run() {
          readAndParseFile();
    }
});
updateUIWithContentOfFile();

调用和阻止会以合法方式有效阻止当前的EDT。 它产生一个单独的线程来运行run()方法,当该run方法完成时,它会返回到EDT。 当invokeAndBlock运行时,所有事件和EDT行为仍然有效,这是因为invokeAndBlock()一直在内部调用主线程循环。

注意,这会稍微降低性能,建议不要嵌套invokeAndBlocks(或过度使用它们)。 但是,它们在使用多个线程/ UI时非常方便。

当我已经在EDT上时,为什么我要调用Serially?

我们在上一篇文章中讨论了callSerially,但是一个被误解的主题之一就是为什么当我们仍然在EDT上时,为什么要调用此方法。 如果在EDT上调用callSerially,则LWUIT的原始版本曾经引发IllegalArgumentException,因为这似乎没有意义。但是,这确实是有道理的,我们可以使用示例进行解释。 例如,说我们有一个按钮,该按钮具有与其事件相关的很多功能,例如:

  1. 用户添加了一个动作侦听器以显示一个对话框。
  2. 用户安装的框架向该按钮添加了一些日志记录。
  3. 该按钮在释放动画时重新绘制释放动画。

但是,如果我们处理的第一个事件(对话框)可能导致以下事件发生问题,则可能会导致问题。 例如,对话框将阻止EDT(使用invokeAndBlock),事件将继续发生,但是由于事件“我们已经发生”,因此按钮将重新绘制,而框架日志将不会发生。 如果我们显示一个表单,该表单可能触发依赖于当前存在的当前表单的逻辑,则也可能发生这种情况。

解决此问题的方法之一是仅用callSerially包装动作侦听器主体。 在这种情况下,callSerially会将事件推迟到EDT的下一个周期(循环),并让链中的其他事件完成。 请注意,您不应该正常使用此函数,因为它会增加开销,并使应用程序流程复杂化,但是当您在事件处理过程中遇到问题时,建议您尝试一下以查看其原因。

翻译自: https://www.javacodegeeks.com/2014/11/callserially-the-edt-invokeandblock-part-2.html

edt嵌入式确定性测试

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值