Java desktop - how to separate database access from the UI thread?

。_饼干妹妹 提交于 2019-12-24 00:16:53

问题


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());

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 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. 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.

Stack trace:

    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)

回答1:


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();

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.

EDIT:

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

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

  1. The user clicks a button in the UI. The UI thread puts an event object (DataWantedEvent) on a queue (java.util.Queue), changes a label ("Waiting for data...") and then goes on and waits for other user interactions.
  2. The db layer thread takes the event form the queue and queries the database. The result is posted back on another queue in a result object.
  3. A UI thread (not the main thread probably) takes the result object from the result queue and updates the 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.




回答2:


You can have a listener implementation that directly updates the UI. Something like a function callback, that gives an event to the UI thread.

That way , your UI thread can continue serving the input request, assuming you business logic does not require it to be a synchronous db request.

You could always do it asynchronously.

HTH.



来源:https://stackoverflow.com/questions/8955766/java-desktop-how-to-separate-database-access-from-the-ui-thread

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!