2010-09-06 2 views
3

Я хотел бы узнать больше о том, насколько можно контролировать, где работает каждый актер Scala. Я оказался в несколько конкретном случае: требуется высокая реактивность, значительная часть кода критически важна, и, что хуже всего, я нахожусь на Android. Имея это в виду, моя главная цель: сделать код максимально понятным и понятным.Управление потоками актеров Scala

Что бы идеально хотите достичь (некоторые из них звучат неразумно/совершенно глупо сначала прочитать мотивировки ниже)
- Я хотел бы быть в состоянии ответить на некоторые сообщения в некоторых частности, всегда то же самое, произвольные поток, но мне не нужно блокировать его, чтобы ждать сообщений.
- Я бы хотел, чтобы большинство моих обработок выполнялось в пуле рабочих потоков, идеально автоматическое изменение размера, поскольку актеры Scala поддерживают, гарантируя, что эта обработка никогда не будет выполняться на произвольном потоке выше.

Эти требования обусловлены необходимостью Android: в платформе Android используется специальный поток для настройки интерфейса пользователя, и если вы касаетесь любого объекта пользовательского интерфейса из другого потока, вы получаете исключение. Таким образом, он применяет какую-то модель потоков/блокировок, которая именно то, что я пытаюсь работать. Но в любом случае, так оно и есть: я должен обеспечить, чтобы часть моей обработки, а именно то, что имеет дело с объектами пользовательского интерфейса, работает на этом потоке, а другое нет, потому что в ракурсе досадно говорится, что я должен это делать. Досадный побочный эффект от этого до тех пор, пока этот поток обрабатывает мой код, пользовательский интерфейс перестает обновляться, и мое приложение перестает быть отзывчивым. Поэтому мне нужно убедиться, что этот поток не выбирается случайным образом для долгого кода, который я мог бы использовать в некоторых реакциях {}, и в идеале, что он никогда не обрабатывает то, что может быть сделано другим потоком.

Андроид-каркас предоставляет класс Handle, который реализует какую-то передачу сообщений - вы отправляете его Runnable и запускаете его в потоке пользовательского интерфейса. Я могу использовать это, если нужно. Создание Runnable каждый раз значительно загромождает код - одна вещь, которую можно сделать, - это инкапсулировать его каким-то способом, чтобы я мог написать что-то вроде
onUIThread {/ * некоторый код * /}
... который намного лучше, чем новый Runnable() {def run() {}}. С другой стороны, это в основном то, что делает функция onUIThread, поэтому я бы создал два закрытия - и тогда мне пришлось бы иметь дело с деталями распределения памяти для закрытия. Я должен буду, потому что каждый раз, когда я выделяю объект, GC получает возможность запускать и на Android, что обычно составляет 150 мс при выполнении, что может испортить мой пользовательский опыт, если это происходит в критическом пути выполнения.

Таким образом, в конце концов:
- Есть ли у меня какой-либо способ статически связать актера с резьбой, так что я мог бы UI актера, реагировать {} внутри него, и всегда иметь код, выполняемый в потоке пользовательского интерфейса ?/* Я знаю, что это плохая конструкция сама по себе, прочитайте объяснение выше, чтобы понять, почему я не могу помочь. */
- У меня есть способ гарантировать, что этот конкретный поток никогда не будет рассмотрен для ответа на сообщение в реагировать {}? - Любые предложения о том, что я мог бы сделать, учитывая мои ограничения, чтобы улучшить четкость кода?

ответ

5

Вы можете реализовать планировщик клиентов, расширив признак IScheduler, который подталкивает задачи к потоку ui, а затем переопределяет метод планировщика на вашем акторе, который должен запускаться в потоке ui.

Кто-то попытался это с свинг некоторое время назад я и думаю, что это сработало: http://scala-programming-language.1934581.n4.nabble.com/scala-Swing-event-thread-actors-td1987246.html

Тогда пусть другие актеры использовать обычный планировщик.

Но я укажу, что реакция {} приводит к созданию замыкания, которое в конечном итоге завершается в runnable. Он также использует исключения для управления потоком, что приводит к значительным накладным расходам (я не знаю, сколько на Dalvik). Поэтому, если закрытие GC действительно ухудшает производительность вашего приложения, я сомневаюсь, что актеры вас спасут.

+0

Это похоже на то, что мне нужно. Большое вам спасибо, я это рассмотрю! О закрытии это только означает, что я должен быть осторожным, чтобы не выделять для них память, пока выполняется критический код, потому что это то, что запускает (предварительный) GC, который нарушает мою производительность, даже если ему нечего чистить. Но это было бы так же, если бы я сам создавал Runnables, поэтому ... нет бесплатного обеда. В любом случае, спасибо за хороший ответ! – Jean

Смежные вопросы