Pozwolę sobie najpierw powiedzieć, że mam całkiem spore doświadczenie w Javie, ale dopiero niedawno zainteresowałem się językami funkcjonalnymi. Niedawno zacząłem patrzeć na Scalę, która wydaje się bardzo fajnym językiem.
Jednak czytałem o strukturze aktora Scali w programowaniu w Scali i jest jedna rzecz, której nie rozumiem. W rozdziale 30.4 jest napisane, że używanie react
zamiast receive
umożliwia ponowne użycie wątków, co jest dobre dla wydajności, ponieważ wątki są drogie w JVM.
Czy to oznacza, że jeśli pamiętam, żeby zadzwonić react
zamiast dzwonić receive
, mogę założyć tylu aktorów, ilu zechcę? Zanim odkryłem Scalę, bawiłem się z Erlangiem, a autor Programming Erlang chwali się, że bez wysiłku stworzył ponad 200 000 procesów. Nie chciałbym tego robić z wątkami Java. Na jakie ograniczenia patrzę w Scali w porównaniu z Erlangiem (i Javą)?
Jak działa ponowne użycie tego wątku w Scali? Załóżmy dla uproszczenia, że mam tylko jeden wątek. Czy wszyscy aktorzy, których zacznę uruchamiać sekwencyjnie w tym wątku, czy będzie miało miejsce przełączanie zadań? Na przykład, jeśli uruchomię dwóch aktorów, którzy wysyłają sobie wiadomości ping-pong, czy zaryzykuję zakleszczenie, jeśli zaczną się w tym samym wątku?
Według Programming in Scala pisanie aktorów do użycia react
jest trudniejsze niż z receive
. Brzmi to wiarygodnie, ponieważ react
nie wraca. Jednak książka pokazuje, jak można umieścić react
wewnątrz pętli za pomocą Actor.loop
. W rezultacie otrzymujesz
loop {
react {
...
}
}
który wydaje mi się dość podobny do
while (true) {
receive {
...
}
}
który został użyty wcześniej w książce. Mimo to książka mówi, że „w praktyce programy będą wymagały co najmniej kilku receive
”. Więc czego tu brakuje? Co może receive
zrobić, react
czego nie może poza powrotem? I dlaczego mnie to obchodzi?
Na koniec dochodzę do sedna tego, czego nie rozumiem: książka ciągle wspomina, jak używanie react
umożliwia odrzucenie stosu wywołań w celu ponownego użycia wątku. Jak to działa? Dlaczego konieczne jest odrzucenie stosu wywołań? I dlaczego można odrzucić stos wywołań, gdy funkcja kończy się przez zgłoszenie wyjątku ( react
), ale nie wtedy, gdy kończy się zwracaniem ( receive
)?
Mam wrażenie, że programowanie w Scali tuszowało tu kilka kluczowych kwestii, a szkoda, bo poza tym to naprawdę świetna książka.