Должен ли я использовать Java "рабочий поток" для этого приложения моделирования CPU? - PullRequest
3 голосов
/ 26 июля 2011

Я пишу эмулятор старого компьютера на Java / Swing, и мне кажется, что я обнаружил проблему с дизайном, которая у меня возникла. Как ни странно это приложение, я подозреваю, что кто-то найдет «образец» этой проблемы.

Я должен добавить, что я все еще новичок в ООП, графических интерфейсах и шаблонах проектирования.

Машина имеет поток GUI (консоль) - с кнопками и переключателями, а также поток модели (ЦП), с которым консоль взаимодействует, чтобы события консоли изменяли состояние ЦП. Консоль, конечно, управляется событиями из очереди событий AWT. Консоль обменивается данными с процессором, помещая в очередь сообщения в приоритетной очереди блокировки, которую получает процессор. Таким образом, ЦП также структурирован как цикл обработки событий. Пока все хорошо.

Проблема в том, что, когда вы нажимаете START на консоли, вы хотите, чтобы процессор начал выполнять любую программу, которая находится в его памяти. Он по-прежнему должен реагировать на броски переключателей и нажатия кнопок (например, STOP) с консоли, но в основном ему нужно сидеть и вращаться в цикле fetch-decode-execute инструкции.

И даже это некоторое время не было проблематично: у меня был метод с именем Cycle () , который выполнял бы один конкретный «цикл» текущей инструкции и затем возвращал, чтобы его немедленно пересылали для выполнения следующий цикл. Я поместил вызов Cycle () в цикл выполнения ЦП и опрашивал очередь сообщений после каждого цикла. Если процессор был остановлен, цикл выполнения просто будет ждать в очереди сообщений.

Теперь: я выполняю инструкции ввода / вывода, например, Читать карту. Для одного из циклов необходимо отправить запрос данных на рассматриваемое периферийное устройство (само реализованное в виде графического интерфейса пользователя / модели, работающей в отдельных потоках), а затем ждать данных прибывать. Это полностью нарушает представление о том, что процессор является простым циклом обработки событий, который получает сообщения и воздействует на них, не вызывая блокировку в процессе. Этот новый цикл будет блокироваться. И если оператор не загрузил колоду карт в считыватель, он может заблокироваться на длительное время.

Я думал о выделении цикла инструкции fetch-decode-execute в отдельный «рабочий» поток, но я не думаю, что он подходит, так как рабочие потоки (насколько я понимаю) предназначены для асинхронной работы до завершения , и не продолжайте взаимодействовать с их родительским потоком во время работы. (На самом деле, я не могу понять, почему «рабочий поток» должен когда-либо завершаться.) Кроме того, в настоящее время не требуется синхронизация, когда циклу требуется доступ к данным, которые могут быть одновременно изменены в результате нажатий клавиш консоли.

Так как мне скомбинировать обработку, "управляемую событиями", с традиционным пакетным процессом, который должен явно ждать сообщений перед продолжением?

Ответы [ 2 ]

2 голосов
/ 26 июля 2011

Рабочие потоки (насколько я понимаю) предназначены для асинхронного завершения до завершения и не продолжают взаимодействовать с родительским потоком во время работы.

Обычная реализация, SwingWorker , не имеет определенного ограничения по времени, и она может непрерывно передавать результаты в потоке отправки событий *1008* в течение своего срока службы с помощью метода publish(). Единственная потенциальная проблема, которую я вижу, заключается в том, что соответствующий метод process() может получить объединенные результаты. Для справки, вот пример .

В качестве альтернативы, ваша модель процессора может использовать таймер для запуска цикла fetch-decode-execute. javax.swing.Timer удобно, поскольку его обработчик событий действия выполняется в потоке диспетчеризации событий . Вам придется синхронизировать доступ к любым совместно используемым данным, используя методы, описанные в этой статье .

Наконец, вы можете посмотреть на этот ответ , в котором упоминается эмуляция 6502 в Java.

2 голосов
/ 26 июля 2011

В типичной реальной системе каждое отдельное устройство фактически будет работать параллельно (т.е. в своем собственном потоке), но, безусловно, имеет смысл смоделировать его в моделировании как отдельный поток.Вы захотите убедиться, что вы внедрили какой-то аналог системы прерываний в реальных процессорах для обработки синхронизации, когда рабочий завершил свою работу (например, новая очередь приоритетов для перехвата «прерываний ввода-вывода» и т. П.).).Возможно, вам будет полезно подобрать копию Проект операционной системы UNIX Мориса Баха.В нем подробно рассказывается о том, как UNIX взаимодействует с базовым оборудованием, и он может стать хорошим ресурсом для вашего проекта.

...