У меня есть ActorSystem, который состоит из трех актеров, MasterActor, PrinterActor и BlockerActor:Akka актер заблокирован другой актер работает процессор интенсивной работы
PrinterActor просто спит в течение одной секунды, то печатает что-то:
public class PrinterActor extends UntypedActor {
@Override
public void onReceive(Object msg) throws Exception {
Thread.sleep(1000);
System.out.println("elapsed time is " + (System.currentTimeMillis()-(Long)msg));
}
}
BlockerActor делает некоторые CPU-интенсивная работа:
public class BlockerActor extends UntypedActor {
@Override
public void onReceive(Object msg) throws Exception {
long count=0;
for (int i=0; i<5000; i++) {
for (int j=0; j<1000000000; j++) {
count++;
}
}
System.out.println("count is " + count);
}
}
MasterActor создает выше двух актеров, то говорит им, чтобы начать работать на то же самое время:
public class MasterActor extends UntypedActor {
@Override
public void onReceive(Object msg) throws Exception {
ActorRef printer = getContext().actorOf(Props.create(PrinterActor.class), "printerActor");
ActorRef blocker = getContext().actorOf(Props.create(BlockerActor.class), "blockerActor");
blocker.tell("start", getSelf());
printer.tell(System.currentTimeMillis(), getSelf());
}
}
Основной метод создает экземпляр ActorSystem, создает MasterActor под ним затем посылает актера начало сообщения.
public class App {
public static void main(String[] args) {
ActorSystem actorSystem = ActorSystem.create("Test");
ActorRef master = actorSystem.actorOf(Props.create(MasterActor.class), "masterActor");
master.tell("start", null);
}
}
Я ожидал, что PrinterActor завершится быстро, но это было не так. Смотрите ниже вывод:
count is 5000000000000
elapsed time is 106856
Она смотрит на меня PrinterActor фактически не получают отдельный поток, но делил один поток с двумя другими субъектами в системе. У меня такое впечатление, потому что если я изменять реализацию BlockerActor на:
public class BlockerActor extends UntypedActor {
@Override
public void onReceive(Object msg) throws Exception {
Thread.sleep(60 * 1000);
}
}
PrinterActor будет работать намного быстрее:
elapsed time is 1004
Обратите внимание, что я не настроить любого диспетчера для моих актеров. Поэтому все они должны использовать диспетчер по умолчанию для системы, у которого есть пул из 3.0 (коэффициент параллелизма по умолчанию) * количество процессоров (8 ядер на моей машине) = 24 потока. Я даже пытался предоставить PrinterActor PinnedDispatcher (выделенный поток), но все еще не мог заставить PrinterActor ускоряться, когда работал над BlockerActor.
Теперь я действительно смущен. Разве вы не должны проявлять некоторую степень параллелизма при использовании таких актеров? Это ожидаемое поведение Акки или я сделал что-то неправильно?
PS: Я провел программу в Eclipse, с Акку 2.3.6
Я побежал это с последней версией Акки внутри Eclipse, и все работало точно так, как ожидалось. Печатный агент печатал свое сообщение примерно через 1 секунду, а затем блок-сервер печатал его сообщение спустя некоторое время. Не уверен, как вы управляете этим по-другому, чтобы заставить его делать то, что вы видите здесь. – cmbaxter
Я могу воспроизвести эту проблему последовательно с точно указанным кодом. Возможно, попробуйте увеличить время сна в PrinterActor до более высокого числа, как две секунды, и посмотреть, что произойдет. Потому что, если я сброшу время сна ниже 900 мс или не поставлю заявление о спящем состоянии, принтер полностью завершит работу. Кажется, что принтер фактически получает некоторое процессорное время в начале, но затем полностью блокируется, если он еще не выполнен. Возможно, в вашем случае принтер закончил прямо перед «эффектом блокировки». В любом случае спасибо за отзыв! – zhuke2