我最近使用Quartz调度程序来运行涉及数据库访问的一些后台进程(例如报告生成)。现在,此后台任务在不同的线程中运行。但是,数据库访问在我的应用程序的中心点完成,类似
System.err.println("CURRENT THREAD: "+ Thread.currentThread().getName());
在执行实际查询之前,打印“main”。因此,我认为数据库读取是由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)
答案 0 :(得分:1)
即使您说计划任务运行查询(?),您的数据库查询似乎也是从UI线程运行的。当然,您可以打印出访问数据库的堆栈跟踪:
new Exception().printStacktrace();
对于您提出的解决方案:如果您的数据库查询速度很慢,那么它似乎是一个不错的设计,否则会冻结您的UI。您可以在UI层和数据库层之间实现一个事件系统,也许是一种基于队列的简单方法。
修改强>
最有可能找到如何实施基于事件的解决方案的示例。
免责声明:多年来我没有做过任何真正的用户界面编程。
可能不需要将结果对象发布回UI的队列。可以直接调用更新方法。
如果用户单击取消按钮,则可以忽略更新事件/回调,或者,如果可能,可以取消db查询。
答案 1 :(得分:0)
您可以拥有直接更新UI的侦听器实现。类似于函数回调的东西,它为UI线程提供了一个事件。
这样,您的UI线程可以继续提供输入请求,假设您的业务逻辑不要求它是同步数据库请求。
你总是可以异步地进行。
HTH。