import akka.actor.{Actor, ActorSystem, Props}
// 액터 정의
class HelloActor extends Actor {
def receive: Receive = {
case "hello" =>
sender() ! "world"
case msg =>
println(s"Unknown message: $msg")
}
}
// 메인 또는 테스트 앱
object HelloActorApp extends App {
// 액터 시스템 생성
val system = ActorSystem("HelloSystem")
// 액터 인스턴스 생성
val helloActor = system.actorOf(Props[HelloActor], name = "helloActor")
// 응답을 기다릴 임시 액터 생성
import akka.pattern.ask
import akka.util.Timeout
import scala.concurrent.duration._
import scala.concurrent.Await
import scala.concurrent.ExecutionContext.Implicits.global
implicit val timeout: Timeout = Timeout(5.seconds)
// 메시지 전송 및 응답 대기
val future = helloActor ? "hello"
val result = Await.result(future, timeout.duration)
println(s"응답: $result") // "world" 출력
// 종료
system.terminate()
}
|
"hello" 메시지를 받으면 sender() ! "world"로 응답을 보냄
ask 패턴(?)을 사용하여 응답을 Future로 받음
Await.result로 블로킹 방식으로 응답을 출력
public class HelloActor extends AbstractActor {
// 액터 생성 팩토리
public static Props props() {
return Props.create(HelloActor.class);
}
@Override
public Receive createReceive() {
return receiveBuilder()
.matchEquals("hello", msg -> {
getSender().tell("world", getSelf());
})
.matchAny(msg -> {
System.out.println("Unknown message: " + msg);
})
.build();
}
}
public class HelloActorApp {
public static void main(String[] args) throws Exception {
ActorSystem system = ActorSystem.create("HelloSystem");
ActorRef helloActor = system.actorOf(HelloActor.props(), "helloActor");
// 메시지 보내고 응답 기다리기
Future<Object> future = Patterns.ask(helloActor, "hello", 5000);
String result = (String) Await.result(future, Duration.create(5, TimeUnit.SECONDS));
System.out.println("응답: " + result); // "world"
system.terminate();
}
}
|
public class HelloActor : ReceiveActor
{
public HelloActor()
{
Receive<string>(msg =>
{
if (msg == "hello")
{
Sender.Tell("world");
}
else
{
Console.WriteLine($"Unknown message: {msg}");
}
});
}
}
class Program
{
static async Task Main(string[] args)
{
using var system = ActorSystem.Create("HelloSystem");
var helloActor = system.ActorOf<HelloActor>("helloActor");
// Ask 패턴으로 메시지 보내고 응답 받기
var response = await helloActor.Ask<string>("hello", TimeSpan.FromSeconds(5));
Console.WriteLine($"응답: {response}"); // "world"
await system.Terminate();
}
} |
class HelloActor : AbstractActor() {
override fun createReceive(): Receive {
return receiveBuilder()
.matchEquals("hello") {
sender.tell("world", self)
}
.matchAny {
println("Unknown message: $it")
}
.build()
}
companion object {
fun props(): Props = Props.create(HelloActor::class.java)
}
}
fun main() {
val system = ActorSystem.create("HelloSystem")
val helloActor = system.actorOf(HelloActor.props(), "helloActor")
val future = Patterns.ask(helloActor, "hello", 5000)
val result = Await.result(future, Duration.create(5, TimeUnit.SECONDS)) as String
println("응답: $result") // world 출력
system.terminate()
} |
코틀린은 액터모델을 채택했기때문에 서드파티툴없이 액터모델 이용가능합니다.
(akka,pekko 이용시 액터모델이 스트림,클러스터로 확장되는 툴은없기때문에 직접 구현해야함)
import kotlinx.coroutines.channels.actor
// 메시지 정의
sealed class Message
data class Greet(val replyTo: CompletableDeferred<String>) : Message
object Unknown : Message
// 액터 함수
fun CoroutineScope.helloActor() = actor<Message> {
for (msg in channel) {
when (msg) {
is Greet -> msg.replyTo.complete("world")
else -> println("Unknown message received: $msg")
}
}
}
fun main() = runBlocking {
val actor = helloActor()
val response = CompletableDeferred<String>()
actor.send(Greet(response))
println("응답: ${response.await()}") // 출력: world
actor.close()
} |
// hello_actor.py
import ray
# Ray 초기화
ray.init()
# 액터 클래스 정의
@ray.remote
class HelloActor:
def say(self, msg):
if msg == "hello":
return "world"
else:
return f"Unknown message: {msg}"
// main.py
import ray
from hello_actor import HelloActor
ray.init(ignore_reinit_error=True) # 이미 실행 중일 경우 무시
# 액터 생성
actor = HelloActor.remote()
# 메시지 전송 및 응답 받기
response = ray.get(actor.say.remote("hello"))
print(f"응답: {response}") # 출력: world
# 종료
ray.shutdown() |
-module(hello_actor).
-export([start/0, loop/0]).
start() ->
spawn(fun loop/0).
loop() ->
receive
{From, "hello"} ->
From ! "world",
loop();
{From, Msg} ->
From ! {error, "Unknown message: " ++ Msg},
loop()
end.
1> c(hello_actor). % 컴파일
2> Pid = hello_actor:start(). % 액터 시작
3> Pid ! {self(), "hello"}. % 메시지 전송
4> flush(). % 응답 확인
Shell output:
Shell got "world"
|
Lightweight 프로세스 (수십만 개 생성 가능)
모든 액터는 메시지 기반으로 통신
고장 격리 (let it crash 철학)
OTP 사용 시 supervision, 상태 관리, 분산까지 매우 쉬움