Java桌面-如何将数据库访问与UI线程分开? [英] Java desktop - how to separate database access from the UI thread?

查看:184
本文介绍了Java桌面-如何将数据库访问与UI线程分开?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have recently used Quartz scheduler for running some background processes (eg. report generation) that involves database access. Now, this background tasks runs in separate threads. However, the database access in done in a central point in my application, and something like

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

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

prints "main", before executing the actual query. Therefore, i am thinking that the database read is done by the UI thread ("main" thread). This is also confirmed by the fact that the UI loses (in part) his responsiveness. What i want to do, if possible, is to run every database access in a separate thread, so that a Cancel button can be implemented to a query request, if that will become necessary. So, i imagine having this workers:

  • UI线程:负责UI;
  • 数据库访问线程:负责从db检索数据;
  • 预定的后台任务:负责其他所有事情(并使用数据库访问线程).

  • UI thread: responsible for UI;
  • Database access thread: responsible for data retrieving from the db;
  • Scheduled background tasks: responsible for everything else (and using the DB access thread).

这可以实现吗?还是我的方法有更好的选择?

Can this be realized? Or, is there a better alternative to my approach?

P.S.在这一点上,我不想使用某些现有框架来解决此问题(Hibernate,Spring等).我只需要一个自制的工作解决方案.

P.S. I do not want to use at this point some existing frameworks, that address this issue (Hibernate, Spring, etc). I just need a home-brew, working solution.

堆栈跟踪:

    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线程运行的.可以肯定的是,您可以在访问数据库的位置打印出堆栈跟踪记录:

It seems like your db queries are run from the UI thread even though you say that a scheduled task runs the queries (?). To be sure, you can print out a stacktrace where you access the database:

new Exception().printStacktrace();

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

Over to your proposed solution: it seems like a decent design if your db queries are slow and otherwise would freeze your UI. You could implement an event system between your UI layer and the db layer, perhaps a simple queue based approach.

最有可能找到实现基于事件的解决方案的示例.

There are most likely examples to find how to implement a event based solution.

免责声明:多年以来,我还没有做过任何真正的UI编程.

Disclaimer: I haven't done any real UI programming in many years.

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

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

A queue for posting result objects back to the UI might not be needed. An update method could be invoked directly.

如果用户单击取消"按钮,则可以忽略更新事件/回调,或者,如果可能的话,可以取消数据库查询.

If the user clicks a cancel button, the update event/callback could be ignored or, if possible, the db query could be cancelled.

这篇关于Java桌面-如何将数据库访问与UI线程分开?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆