Рабочий стол Java - как отделить доступ к базе данных от потока пользовательского интерфейса? - PullRequest
2 голосов
/ 21 января 2012

Я недавно использовал Quartz scheduler для запуска некоторых фоновых процессов (например, генерация отчетов), которые включают доступ к базе данных.Теперь эти фоновые задачи выполняются в отдельных потоках.Тем не менее, доступ к базе данных осуществляется в центральной точке моего приложения, и что-то вроде

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

выводит «main» перед выполнением фактического запроса.Поэтому я думаю, что чтение базы данных выполняется потоком пользовательского интерфейса («основной» поток).Это также подтверждается тем фактом, что пользовательский интерфейс теряет (частично) его отзывчивость.Что я хочу сделать, если это возможно, это запустить каждый доступ к базе данных в отдельном потоке, чтобы кнопка «Отмена» могла быть реализована в запросе запроса, если это станет необходимым.Итак, я представляю себе таких работников:

  • Поток пользовательского интерфейса: отвечает за пользовательский интерфейс;
  • Поток доступа к базе данных: отвечает за извлечение данных из БД;
  • Запланированные фоновые задачи: ответственность за все остальное (и использование потока доступа к БД).

    Может ли это быть реализовано?Или есть ли лучшая альтернатива моему подходу?

PS На данном этапе я не хочу использовать некоторые существующие платформы, которые решают эту проблему (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 ]

1 голос
/ 21 января 2012

Кажется, что ваши запросы к БД выполняются из потока пользовательского интерфейса, даже если вы говорите, что запланированное задание выполняет запросы (?).Чтобы быть уверенным, вы можете распечатать трассировку стека, где вы получаете доступ к базе данных:

new Exception().printStacktrace();

Перейдите к предложенному вами решению: это выглядит как приличный дизайн, если ваши запросы к БД медленны и в противном случае заморозили бы ваш интерфейс.Вы могли бы реализовать систему событий между вашим уровнем пользовательского интерфейса и уровнем базы данных, возможно, простой подход на основе очереди.

РЕДАКТИРОВАТЬ:

Есть наиболее вероятные примеры, чтобы найти, какреализовать решение, основанное на событиях.

Отказ от ответственности: я много лет не занимался программированием пользовательского интерфейса.

  1. Пользователь нажимает кнопку в пользовательском интерфейсе.Поток пользовательского интерфейса помещает объект события (DataWantedEvent) в очередь (java.util.Queue), изменяет метку («Ожидание данных ...»), а затем продолжается и ожидает других действий пользователя.
  2. Поток уровня БД принимает событие из очереди и запрашивает базу данных.Результат отправляется обратно в другую очередь в объекте результата.
  3. Поток пользовательского интерфейса (вероятно, не основного потока) берет объект результата из очереди результатов и обновляет пользовательский интерфейс.

Очередь для публикации объектов результатов в пользовательском интерфейсе может не потребоваться.Метод обновления может быть вызван напрямую.

Если пользователь нажимает кнопку отмены, событие / обратный вызов обновления можно игнорировать или, если возможно, запрос базы данных можно отменить.

0 голосов
/ 22 января 2012

У вас может быть реализация прослушивателя, которая напрямую обновляет пользовательский интерфейс.Что-то вроде обратного вызова функции, которое передает событие в поток пользовательского интерфейса.

Таким образом, ваш поток пользовательского интерфейса может продолжать обслуживать входной запрос, предполагая, что ваша бизнес-логика не требует, чтобы это был синхронный запрос БД.

Вы всегда можете сделать это асинхронно.

HTH.

...