gpt4 book ai didi

java - 可重用 Executor、ServiceExecutor 等接口(interface)的用途

转载 作者:行者123 更新时间:2023-11-30 08:43:32 25 4
gpt4 key购买 nike

我正在使用支持长时间运行的 CPU 密集型操作的 javaFX 构建一个 GUI 应用程序,例如 Prime95 或 Orthos。

我遇到的一个问题是试图让计数器很好地递增。如果您考虑一个 ElapsedTime 字段,它带有一个毫秒分辨率的递增计数器,我需要的是在 UI 线程上调用一个作业来调用 elapsedTimeTextField.setText("00:00:00.001") 在相应调用 elapsedTimeTextField.setText("00:00:00.002") 之前 1 毫秒发生。我还需要让 UI 线程在这两个调用之间完成更重要的工作。

构造代码来执行此操作一直很乏味,并且导致我们的许多 Controller 类创建线程,这些线程只是在类似于以下的代码上循环:

Thread worker = new Thread(this::doUpdates);
worker.start();

//...

private void doUpdates(){
while(true){
String computedTime = computeTimeToDisplay();
runLaterOnUI(() -> textField.setText(computedTime));
sleep(DUTY_CYCLE_DOWNTIME);
}
}

虽然这完成了工作,但它并不受欢迎,因为:

  • 很难进行单元测试:在测试环境中,您要么必须修改此代码以在它完成第一次通过时发出某种信号(通常是倒计时锁存器),要么您必须做一些愚蠢的非-确定性和任意性 sleep()s
  • 它没有任何类型的回退:如果 UI 线程被作业淹没,此代码将加剧问题。某种重新排队方案,其中停机时间考虑了作业的延迟,并且更可取某种硬编码 sleep ,因为这意味着如果 UI 作业被淹没,我们不会询问它工作不当。
  • 除了线程默认处理程序外,它没有集中的异常处理。这意味着如果在 computeTimeToDisplay() 方法中(或者在 runLaterOnUI 调用或 sleep() 中引发异常调用)文本字段将不再更新

我已经分别相当好地解决了这些问题中的每一个问题,但我没有任何明显且可重复使用的习惯用法来解决这三个问题。

怀疑 FutureTaskExecutorServiceExecutor、 etc 类(java.util.concurrent 包中的类不是锁或集合)可以帮助我实现这个目标,但我不确定如何使用它们。

有人可以建议阅读一些文档和遵循一些习语来帮助我实现这些目标吗?对于这种并发作业,是否有商定的惯用语——不涉及匿名类并包含最少的样板?

最佳答案

我建议使用 ScheduledThreadPoolExecutor核心池大小为 1,线程优先级可选为 Thread.NORM_PRIORITY + 1(使用 ThreadFactoryBuilder 创建 ThreadFactory高于标准优先级)用于 UI 线程 - 这将允许您使用 ScheduledThreadPoolExecutor#scheduleAtFixedRate 安排任务,例如计数器增量。不要在此执行器上执行除 UI 任务之外的任何其他任务 - 在具有标准优先级的单独 ThreadPoolExecutor 上执行您的 CPU 任务;如果你有16 个逻辑核心然后创建一个具有 16 个核心线程的 ThreadPoolExecutor 以在 UI 线程空闲时充分利用您的计算机,并让虚拟机负责确保 UI 线程在空闲时执行其作业应该。

关于java - 可重用 Executor、ServiceExecutor 等接口(interface)的用途,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34213963/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com