Java桌面 - 如何从UI线程中分离数据库访问?

时间:2012-01-21 18:59:46

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

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

System.err.println("CURRENT THREAD: "+ Thread.currentThread().getName());
在执行实际查询之前,

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

  • UI线程:负责UI;
  • 数据库访问线程:负责从数据库检索数据;
  • 计划的后台任务:负责其他一切(并使用数据库访问线程)。

    这可以实现吗?或者,是否有更好的替代方法?

P.S。我不想在这一点上使用一些解决这个问题的现有框架(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)

2 个答案:

答案 0 :(得分:1)

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

new Exception().printStacktrace();

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

修改

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

免责声明:多年来我没有做过任何真正的用户界面编程。

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

    如果用户单击取消按钮,则可以忽略更新事件/回调,或者,如果可能,可以取消db查询。

答案 1 :(得分:0)

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

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

你总是可以异步地进行。

HTH。