Позвольте мне сначала сказать, что у меня довольно большой опыт работы с Java, но только недавно он заинтересовался функциональными языками. Недавно я начал смотреть на Scala, который кажется очень хорошим языком.
Тем не менее, я читал об Scala Actor Framework в Программирование в Scala , и есть одна вещь, которую я не понимаю. В главе 30.4 говорится, что использование react
вместо receive
позволяет повторно использовать потоки, что хорошо для производительности, поскольку потоки в JVM дороги.
Значит ли это, что, если я не забуду позвонить react
вместо receive
, я могу запустить столько актеров, сколько захочу? Прежде чем открыть Scala, я играл с Эрлангом, и автор Программирование на Эрланге может похвастаться тем, что порождает более 200 000 процессов без единого пота. Я бы не хотел делать это с потоками Java. На какие ограничения я смотрю в Scala по сравнению с Erlang (и Java)?
Кроме того, как этот поток повторно использует работу в Scala? Давайте для простоты предположим, что у меня есть только один поток. Будут ли все актеры, с которыми я начинаю, работать последовательно в этой теме, или произойдет какое-то переключение задач? Например, если я запускаю двух актеров, которые пинг-понг сообщают друг другу, рискну ли я зайти в тупик, если они запущены в одном потоке?
Согласно Программирование в Scala , написание актеров для использования react
сложнее, чем с receive
. Это звучит правдоподобно, так как react
не возвращается. Тем не менее, книга продолжает показывать, как вы можете поместить react
в цикл, используя Actor.loop
. В результате вы получите
loop {
react {
...
}
}
, который мне кажется довольно похожим на
while (true) {
receive {
...
}
}
, который используется ранее в книге. Тем не менее, в книге говорится, что «на практике программам потребуется по меньшей мере несколько receive
». Так чего мне здесь не хватает? Что может receive
сделать, чего не может react
, кроме возврата? И почему меня это волнует?
Наконец, в центре всего того, что я не понимаю: в книге постоянно упоминается, как использование react
позволяет отказаться от стека вызовов для повторного использования потока. Как это работает? Почему необходимо отказаться от стека вызовов? И почему стек вызовов может быть отброшен, когда функция завершается с помощью исключения (react
), но не тогда, когда она завершается возвратом (receive
)?
У меня сложилось впечатление, что Программирование в Scala затмило некоторые ключевые вопросы здесь, что является позором, потому что в остальном это действительно превосходная книга.