java线程立即更新UI

2024-02-17

我有一个 javaFX 应用程序,可以可视化计算几何算法。算法的执行发生在另一个线程中,我们称之为mainComputingThread。 算法可以通过添加/删除/修改形状随时更新 UI。 所以代码将如下所示:

//do some computaions (1)
updateUI();
//do some more calculations (2)

我想知道的是updateUI方法立即更新 UI 并阻止调用线程进一步运行(标记为 (2)),直到 UI 更新完成。

我想到了布尔守卫。所以代码可能如下所示:

updateUI(){
   boolean guard = false;
   Platform.runLater(new Runnable()
   {
      run(){
        //do the actual update
        guard = true;
      }
   });
   while(guard==false);
}

我希望你明白我的意思。我真的很好奇是否有更好的解决方案来解决这个问题......


简单的方法:阻塞后台线程直到更新完成:

您需要更新 FX 应用程序线程上的 UI。通常,您可以通过传递一个简单的Runnable to Platform.runLater(...).

如果您想等待 ui 更新完成后再继续,请创建一个FutureTask http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/FutureTask.html并将其传递给Platform.runLater(...)。然后你可以打电话get() on the FutureTask,这将阻塞直到任务完成:

private void updateUI() throws InterruptedException {

    // actual work to update UI:
    FutureTask<Void> updateUITask = new FutureTask(() -> {

        // code to update UI...

    }, /* return value from task: */ null);

    // submit for execution on FX Application Thread:
    Platform.runLater(updateUITask);

    // block until work complete:
    updateUITask.get();
}

这让FutureTask处理等待和通知的所有棘手工作:如果可以的话,最好使用更高级别的 API 来完成此类工作。

如果您愿意,您可以将其重构为实用方法,类似于 Dainesch 的答案:

public class FXUtils {

    public static void runAndWait(Runnable run) throws InterruptedException {
        FutureTask<Void> task = new FutureTask<>(run, null);
        Platform.runLater(task);
        task.get();
    }
}

替代方法:确保在任何帧渲染期间消耗的更新不超过一次,如果更新待处理,则阻塞后台线程

这是一种略有不同的方法。创建一个BlockingQueue容量为1持有Runnable更新 UI。从您的后台线程中,提交Runnables 到阻塞队列:由于阻塞队列最多只能容纳一个元素,因此如果已经有一个元素处于挂起状态,则会阻塞。

要实际执行队列中的更新(并删除它们,以便可以添加更多更新),请使用AnimationTimer。这看起来像:

private final BlockingQueue<Runnable> updateQueue = new ArrayBlockingQueue<>(1);

后台线程代码:

// do some computations...

// this will block while there are other updates pending:    
updateQueue.put(() -> {
    // code to update UI
    // note this does not need to be explicitly executed on the FX application
    // thread (no Platform.runLater()). The animation timer will take care of that
});

// do some more computations

创建计时器来消耗更新:

AnimationTimer updateTimer = new AnimationTimer() {

    @Override
    public void handle(long timestamp) {
        Runnable update = updateQueue.poll();
        if (update != null) {
            // note we are already on the FX Application Thread:
            update.run();
        }
    }
};

updateTimer.start();

这基本上确保了任何时候都不会安排超过一个更新,并且后台线程会阻塞,直到消耗完任何挂起的更新为止。动画计时器检查(无阻塞)每个帧渲染上的挂起更新,确保执行每个更新。这种方法的好处是,您可以增加阻塞队列的大小,有效地保留待处理更新的缓冲区,同时仍然确保在任何单帧渲染期间消耗的更新不超过一个。如果偶尔有比其他计算花费更长时间的计算,这可能会很有用;它使这些计算有机会在其他计算等待执行时进行计算。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

java线程立即更新UI 的相关文章

随机推荐

  • 从公钥+私钥创建 RSAParamaters 对象

    我需要使用私钥和公钥 key 和 cer 文件 在 Net 中创建 RSAParameters 对象 是否可以在 Net 中做到这一点而不使用第三方软件 如果是这样 我应该去哪里寻找 我最终需要从该对象中提取指数 模数 D P Q DP D
  • XCode 4.3 命令行工具包校验和无效

    Apple 提供的用于使用 Xcode 4 3 安装命令行工具的软件包已损坏 我似乎需要它 因为我正在开发一些命令行工具 有没有人找到 Apple 提供的 Xcode 4 3 的替代命令行包 或者该主题的解决方法 Xcode 包含一个新的
  • 为什么指定的初始化器不能调用其基类中的辅助初始化器?

    根据文档 Objective C 中类的指定初始值设定项必须调用其基类的指定初始值设定项 另一个规则是辅助初始化器必须调用其自己类的指定初始化器 但是 如果遵循第二条规则 为什么指定的初始值设定项不能调用其基类中的辅助初始值设定项 这个基本
  • Flutter 每台设备一个帐户

    如何使一个帐户下的应用程序中只有一个用户 我使用 flutter firebase auth 电子邮件和密码 例如 我有一个帐户 只有我可以从我的设备登录 如果有人发现我的帐户 他将无法登录 谢谢你 我只是给你一个想法如何去做 在cloud
  • SecureRandom 的行为

    尽管在关注了很多文章之后SecureRandom 我在使用时遇到了疑问SecureRandomJava 中的安全 API 在下面的例子中 public class SecureRandomNumber public static void
  • Linux 命令“ll”不起作用[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我可以使用我的用户运行 ll 命令 但不能使用 sudo 它给我错误 因为找不到命令 创建别名ll alias ll ls al
  • Qt 读取访问冲突位于:0x0,flags=0x0(第一次机会)

    我有一段非常简单的代码如下 Letter Vakje geefLetter const return m letter Vakje 类使用 NULL 指针进行初始化m letter 但我仍然收到读取访问冲突错误 有人可以帮忙吗 这是调用该函
  • 如何关闭发生错误后保持打开状态的文件?

    我在用 fid fopen fgfg txt 打开一个文件 有时在我设法关闭文件之前会发生错误 在关闭 Matlab 之前我无法对该文件执行任何操作 如果发生错误 如何关闭文件 首先 你可以使用命令 fclose all 其次 你可以使用试
  • 如何使用 addObserver 闭包方法在 Swift 5 中删除Observer

    这是我的第一篇文章 我是日本 iOS 工程师 这个月刚入职 我有一个麻烦removeObserver的方法NotificationCenter在 Swift 5 中 我通过使用闭包类型将观察者添加到 ViewController VC ad
  • GPX 架构验证问题

    我正在构建一个主要使用 GPX 文件作为输入数据的应用程序 鉴于 gpx 文件应该由 gpx 模式定义 如此处定义 http www topografix com gpx asp http www topografix com gpx as
  • PHP:从哈希中解密密码

    因此 我使用以下代码成功将密码加密为密码哈希 class PassHash blowfish private static algo 2a cost parameter private static cost 10 mainly for i
  • 将 Python Pandas 中的列名称从日期时间对象更改为字符串?

    下列的这个食谱 https stackoverflow com questions 28664103 how to transform a time series pandas dataframe using the index attri
  • AngularJS 应用程序身份验证最佳实践

    我开始构建一个 Web 应用程序 用户需要进行身份验证才能访问不同的模块 我过去一直使用 ASP NET MVC 使用 FormsAuthentication 和服务器会话非常容易 因此每次访问时我不必往返数据库即可获取用户角色或任何其他用
  • gradle进程具有不同替换和重命名规则的资源

    我想在我的 gradle 项目中过滤特定的 java 资源 有些文件应该只替换内容 有些文件也应该重命名 并替换不同的内容 我的 gradle java 项目设置是 gt cat build gradle apply plugin java
  • 有没有办法自动关闭 fork() 上的某些句柄?

    背景 我有一个大型的现有进程 它恰好在 AIX 上 所以基本上是 POSIX 语义 它是一个更大系统的一部分 现有流程设计为连续运行 此过程的一个新要求是处理一种新型的复杂输入流 为了降低风险 我决定分叉 执行一个子进程来执行实际的输入处理
  • 从 Terraform 状态文件中获取特定值

    我已经使用 Terraform 部署了我的基础设施 我注意到我在该州有一些有趣的信息 terraform tfstate 我想提取的 terraform 文件 例如 terraform state show packet device wo
  • Winston 3.0 对控制台上的整个输出进行着色

    我正在开发一个 Node js 应用程序 使用babel cli https www npmjs com package babel cli作为 ES6 转译器 我正在使用温斯顿3 0 https www npmjs com package
  • 删除以哈希开头的所有列表元素

    我有一个包含元素的列表 其中一些以 开头 我怎样才能删除这些元素 我试过 content x for x in content 0 if x but content 0 似乎无效 做这个的最好方式是什么 content x for x in
  • 如何在 Rust 可执行文件中嵌入资源?

    这是这个问题在这里 https stackoverflow com questions 10036769 how do you embed resource files in c对 C 提出同样的要求 基本上 有没有比将其转换为巨大的字节数
  • java线程立即更新UI

    我有一个 javaFX 应用程序 可以可视化计算几何算法 算法的执行发生在另一个线程中 我们称之为mainComputingThread 算法可以通过添加 删除 修改形状随时更新 UI 所以代码将如下所示 do some computaio