【问题标题】:Java desktop - how to separate database access from the UI thread?Java 桌面 - 如何将数据库访问与 UI 线程分开?
【发布时间】:2012-02-15 20:46:54
【问题描述】:

我最近使用 Quartz 调度程序来运行一些涉及数据库访问的后台进程(例如报告生成)。现在,这个后台任务在单独的线程中运行。但是,数据库访问是在我的应用程序的中心点完成的,类似于

System.err.println("CURRENT THREAD: "+ Thread.currentThread().getName());

在执行实际查询之前打印“main”。因此,我认为数据库读取是由 UI 线程(“主”线程)完成的。 UI 失去(部分)响应能力这一事实也证实了这一点。如果可能的话,我想要做的是在单独的线程中运行每个数据库访问,以便可以在查询请求中实现一个取消按钮,如果这将成为必要的话。所以,我想象有这样的工人:

  • UI线程:负责UI;

  • 数据库访问线程:负责从数据库中取回数据;

  • 计划的后台任务:负责其他所有事情(并使用数据库访问线程)。

    这可以实现吗?或者,有没有比我的方法更好的替代方法?

附:在这一点上,我不想使用一些现有的框架来解决这个问题(Hibernate、Spring 等)。我只需要一个自制的、可行的解决方案。

堆栈跟踪:

    at com.mycompany.myproduct.core.db.SQL.executeQuery(SQL.java:260)
at com.mycompany.myproduct.core.db.Database.getAbstractDBObjects(Database.java:285)
at com.mycompany.myproduct.core.db.Database.getAbstractDBObjects(Database.java:305)
at com.mycompany.myproduct.core.util.job.DummyJobProcessor$1.run(DummyJobProcessor.java:61)
at org.eclipse.swt.widgets.RunnableLock.run(Unknown Source)
at org.eclipse.swt.widgets.Synchronizer.runAsyncMessages(Unknown Source)
at org.eclipse.swt.widgets.Display.runAsyncMessages(Unknown Source)
at org.eclipse.swt.widgets.Display.readAndDispatch(Unknown Source)
at com.mycompany.myproduct.core.ui.layers.AbstractView.open(AbstractView.java:915)
at com.mycompany.myproduct.mycompany.open(mycompany.java:196)
at com.mycompany.myproduct.mycompany.main(mycompany.java:365)

【问题讨论】:

  • 阅读您的问题后,您似乎想从不同的线程运行数据库访问,这样您的 UI 就不会受到影响。我说的对吗?

标签: java mysql multithreading user-interface quartz-scheduler


【解决方案1】:

您的数据库查询似乎是从 UI 线程运行的,即使您说计划任务运行查询 (?)。可以肯定的是,您可以打印出访问数据库的堆栈跟踪:

new Exception().printStacktrace();

回到您提出的解决方案:如果您的数据库查询很慢,否则会冻结您的 UI,这似乎是一个不错的设计。你可以在你的 UI 层和 db 层之间实现一个事件系统,也许是一个简单的基于队列的方法。

编辑:

最有可能找到如何实施基于事件的解决方案的示例。

免责声明:我已经很多年没有做过任何真正的 UI 编程了。

  1. 用户单击 UI 中的按钮。 UI 线程将事件对象 (DataWantedEvent) 放入队列 (java.util.Queue),更改标签(“等待数据...”),然后继续等待其他用户交互。
  2. db 层线程从队列中获取事件并查询数据库。结果将在结果对象中的另一个队列中回发。
  3. UI 线程(可能不是主线程)从结果队列中获取结果对象并更新 UI。

可能不需要将结果对象发送回 UI 的队列。可以直接调用更新方法。

如果用户单击取消按钮,更新事件/回调可能会被忽略,或者如果可能,数据库查询可能会被取消。

【讨论】:

  • 你能用事件系统扩展这个想法吗?
【解决方案2】:

您可以拥有一个直接更新 UI 的侦听器实现。类似于函数回调的东西,它给 UI 线程一个事件。

这样,您的 UI 线程可以继续为输入请求提供服务,假设您的业务逻辑不要求它是同步数据库请求。

您总是可以异步执行。

HTH。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-11-24
    • 1970-01-01
    • 2012-09-24
    • 2011-06-20
    • 2015-09-26
    • 2014-05-01
    • 2018-02-08
    相关资源
    最近更新 更多