java-Akka学习笔记

Akka是什么

Akka是JAVA虚拟机平台上构建高并发、分布式和容错应用。Akka用Scala语言编写,同时提供了Scala和Java的开发接口。Akka处理并发的方法基于Actor模型,Actor之间通信的唯一机制就是消息传递
对并发模型进行了更高的抽象

Akka特点:

1.是异步(也可以做到同步)、非阻塞、高性能的事件驱动编程模型

2.是轻量级事件处理(1GB内存可容纳百万级别个Actor)

3.它提供了一种称为Actor的并发模型,其粒度比线程更小,你可以在系统中启用大量的Actor。

4.它提供了一套容错机制,允许在Actor出现异常时进行一些恢复或重置操作。

5.Akka既可以在单机上构建高并发程序,也可以在网络中构建分布式程序,并提供位置透明的Actor定位服务。

Actor是什么

Actor是由状态(state)、行为(behavior)、邮箱(mailbox)三者组成的。

1.状态(state):状态是指actor对象的变量信息,状态由actor自身管理,避免并发环境下的锁和内存原子性等问题。
2.行为(behavior):行为指定的是actor中计算逻辑,通过actor接收到的消息来改变actor的状态。
3.邮箱(mailbox):邮箱是actor之间的通信桥梁,邮箱内部通过FIFO消息队列来存储发送发消息,而接收方则从邮箱中获取消息。
1.0

看到一个比较好的介绍Actor模型:https://www.jianshu.com/p/d803e2a7de8e

Akka学习

1.引入maven

<dependency>            
	<groupId>com.typesafe.akka</groupId>
    <artifactId>akka-actor_2.13</artifactId>
    <version>2.6.0</version>
</dependency>

2.HelloWorld案例

public class HelloWorld {
    
    

    /**
     * 定义一个actor,相当于是java中的继承Thread或者实现Runable接口
     */
    static class ActorDemo extends AbstractActor {
    
    

        //处理消息
        @Override
        public Receive createReceive() {
    
    
            //处理一个具体类型的消息,比如是字符串类型的消息
            Receive build = receiveBuilder().match(String.class,(msg)-> {
    
    
                System.out.println(msg);
            }).build();
            return build;
        }
    }

    public static void main(String[] args) {
    
    
        //创建所有管理actor的系统管理对象
        ActorSystem actorSystem = ActorSystem.create();

        //通过这个系统管理对象创建actor,并返回当前actor的地址,可以理解成现实生活中用户的一个邮箱地址
        ActorRef actorDemo = actorSystem.actorOf(Props.create(ActorDemo.class), "actorDemo");
        //发送消息Object msg(发送消息的内容,任何类型的数据), final ActorRef sender(表示没有发送者(其实是一个叫做deadLetters的Actor))
        actorDemo.tell("HelloWorld",ActorRef.noSender());
    }
}

3.Actor消息转发

static class ActorDemo extends AbstractActor {
    
    

        //处理消息
        @Override
        public Receive createReceive() {
    
    
            //处理一个具体类型的消息,比如是字符串类型的消息
            Receive build = receiveBuilder().match(String.class,(msg)-> {
    
    
                System.out.println(msg);
                //第一种方式
                //getContext()上下文,可以理解成从从Actor管理系统中拿到指定的actor
                ActorRef simpleActor = getContext().actorOf(Props.create(SimpleActorDemo.class), "simpleActor");
                //发送者可以是任何Actor,getSelf()代表发送者是当前类ActorDemo
//                simpleActor.tell("转发成功",getSelf());
                //第二种方式,getContext()最开始发送的发送者Actor。比如有以下Actor,A>B>C,那么最开始发送的发送者Actor就是A
                simpleActor.forward("forward方式,转发成功",getContext());
            }).build();
            return build;
        }
    }

static class SimpleActorDemo extends AbstractActor {
    
    
        //处理消息
        @Override
        public Receive createReceive() {
    
    
            //处理一个具体类型的消息,比如是字符串类型的消息
            Receive build = receiveBuilder().match(String.class,(msg)-> {
    
    
                System.out.println(msg);
            }).build();
            return build;
        }
    }

4.同步接收响应消息->future模式
akka中的future模式有两种,一种阻塞型,一种非阻塞型
阻塞:
Futuref= Patterns.ask(actor,msg,1500);
int re=(int)Await.result(f,timeout);
非阻塞:
Futuref= Patterns.ask(actor,msg,1500);
Patterns.pipe(f,system.dispatcher()).to(actor1)
//即将结果转移到另一个actor中进行处理

static class ActorDemo extends AbstractActor {
    
    

        //处理消息
        @Override
        public Receive createReceive() {
    
    
            //处理一个具体类型的消息,比如是字符串类型的消息
            Receive build = receiveBuilder().match(String.class,(msg)-> {
    
    
                System.out.println(msg);
                //第一种方式
                //getContext()上下文,可以理解成从从Actor管理系统中拿到指定的actor
                ActorRef simpleActor = getContext().actorOf(Props.create(SimpleActorDemo.class), "simpleActor");
                //发送者可以是任何Actor,getSelf()代表发送者是当前类ActorDemo
//                simpleActor.tell("转发成功",getSelf());
                //第二种方式,getContext()最开始发送的发送者Actor。比如有以下Actor,A>B>C,那么最开始发送的发送者Actor就是A
//                simpleActor.forward("forward方式,转发成功",getContext());

                getSender().tell("返回消息",getSelf());
            }).build();
            return build;
        }
    }
public static void main(String[] args) {
    
    
        //创建所有管理actor的系统管理对象
        ActorSystem actorSystem = ActorSystem.create();

        //通过这个系统管理对象创建actor,并返回当前actor的地址,可以理解成现实生活中用户的一个邮箱地址
        ActorRef actorDemo = actorSystem.actorOf(Props.create(ActorDemo.class), "actorDemo");
        //发送消息Object msg(发送消息的内容,任何类型的数据), final ActorRef sender(表示没有发送者(其实是一个叫做deadLetters的Actor))
//        actorDemo.tell("HelloWorld",ActorRef.noSender());
		//设置一秒钟超时时间
        Timeout timeout = new Timeout(Duration.create(1, TimeUnit.SECONDS));
        Future future = Patterns.ask(actorDemo, "发送消息", timeout);
        try {
    
    
            // Await同步获取响应,如果超时了则会抛出java.util.concurrent.TimeoutException
            Object result = Await.result(future, timeout.duration());
            System.out.println(result.toString());
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }
    }

5.Actor 层次结构
1.1
/ 所谓的根监护人。这是系统中所有actor的父亲,当系统被终止时,它也是最后一个被停止的。
/user 这是所有用户创建的actor的父亲。不要被user这个名字所迷惑,他与最终用户没有关系,也和用户处理无关。你使用akka库所创建的所有actor的路径都将以/user/开头。
/system系统监护人。
context.actorOf()来创建新的非顶级actor,即子actor,context.actorOf()的方法和system.actorOf()相同。

public static void main(String[] args) {
    
    
        //创建所有管理actor的系统管理对象
        ActorSystem actorSystem = ActorSystem.create("actorSystem");

        //通过这个系统管理对象创建actor,并返回当前actor的地址,可以理解成现实生活中用户的一个邮箱地址
        ActorRef actorDemo1 = actorSystem.actorOf(Props.create(ActorDemo.class), "actorDemo1");
        ActorRef actorDemo2 = actorSystem.actorOf(Props.create(ActorDemo.class), "actorDemo2");
        System.out.println(actorDemo1);
        System.out.println(actorDemo2);
    }

1.2
两个路径都以akka://actorSystem/开头,所有的actor引用都是合法的URL。akka://是协议字段。
接下来,就像在World Wide Web上一样,URL是一个系统的标识。在这个示例里,系统的名称为actorSystem,它也可以被命名为任意名字。如果开启了多系统间的远程通信,URL里就会包含主机名,以便其他系统可以在网络上找到它。
在这个图片红色圈中的actorDemo1就是对应actorDemo1对象的actorSystem.actorOf中的name参数,而#后面的数字代表当前的Actor的id可以理解成邮箱地址并且是唯一性的。

6.Receive切换

/**
* Receive切换,不同的消息通过不同的Receive来处理
*/
static class becomeActorDemo extends AbstractActor {
    
    

        private int count= 0;

        @Override
        public Receive createReceive() {
    
    
            Receive receiveA = receiveBuilder().match(String.class,(msg)-> {
    
    
                count++;
                System.out.println("receiveA中count的值是:"+count);
                if (msg.equals("3")) {
    
    
                    //如果msg等于3就切换到receiveB
                    getContext().become(receiveB);
                }
            }).build();
            return receiveA;
        }

        Receive receiveC = receiveBuilder().match(String.class,(msg)-> {
    
    
            count++;
            System.out.println("receiveC中count的值是:"+count);
            if (msg.equals("5")) {
    
    
                //就切换回去到receiveA
                getContext().unbecome();
            }
        }).build();

        Receive receiveB = receiveBuilder().match(String.class,(msg)-> {
    
    
            count++;
            System.out.println("receiveB中count的值是:"+count);
            if (msg.equals("4")) {
    
    
                //切换到receiveC
                getContext().become(receiveC);
            }
        }).build();
    }

public static void main(String[] args) {
    
    
        //创建所有管理actor的系统管理对象
        ActorSystem actorSystem = ActorSystem.create("actorSystem");

        //通过这个系统管理对象创建actor,并返回当前actor的地址,可以理解成现实生活中用户的一个邮箱地址
        ActorRef becomeActorDemo = actorSystem.actorOf(Props.create(becomeActorDemo.class), "becomeActorDemo");
        becomeActorDemo.tell("1",ActorRef.noSender());
        becomeActorDemo.tell("2",ActorRef.noSender());
        becomeActorDemo.tell("3",ActorRef.noSender());
        becomeActorDemo.tell("4",ActorRef.noSender());
        becomeActorDemo.tell("5",ActorRef.noSender());
        becomeActorDemo.tell("6",ActorRef.noSender());
    }

运行结果
1.3
Receive切换从receiveA>receiveB>receiveC,再到receiveA。
1.4
如果become方法的第二个参数默认是false

/**
     * Receive切换,不同的消息通过不同的Receive来处理
     */
    static class becomeActorDemo extends AbstractActor {
    
    

        private int count= 0;

        @Override
        public Receive createReceive() {
    
    
            Receive receiveA = receiveBuilder().match(String.class,(msg)-> {
    
    
                count++;
                System.out.println("receiveA中count的值是:"+count);
                if (msg.equals("2")) {
    
    
                    //如果msg等于2就切换到receiveB
                    getContext().become(receiveB);
                }
            }).build();
            return receiveA;
        }

        Receive receiveD = receiveBuilder().match(String.class,(msg)-> {
    
    
            count++;
            System.out.println("receiveD中count的值是:"+count);
            if (msg.equals("5")) {
    
    
                //就切换回去到receiveC
                getContext().unbecome();
            }
        }).build();


        Receive receiveC = receiveBuilder().match(String.class,(msg)-> {
    
    
            count++;
            System.out.println("receiveC中count的值是:"+count);
            if (msg.equals("4")) {
    
    
                //就到receiveD
                getContext().become(receiveD,false);
            }
        }).build();

        Receive receiveB = receiveBuilder().match(String.class,(msg)-> {
    
    
            count++;
            System.out.println("receiveB中count的值是:"+count);
            if (msg.equals("3")) {
    
    
                //切换到receiveC
                getContext().become(receiveC);
            }
        }).build();
    }

    public static void main(String[] args) {
    
    
        //创建所有管理actor的系统管理对象
        ActorSystem actorSystem = ActorSystem.create("actorSystem");

        //通过这个系统管理对象创建actor,并返回当前actor的地址,可以理解成现实生活中用户的一个邮箱地址
        ActorRef becomeActorDemo = actorSystem.actorOf(Props.create(becomeActorDemo.class), "becomeActorDemo");
        becomeActorDemo.tell("1",ActorRef.noSender());
        becomeActorDemo.tell("2",ActorRef.noSender());
        becomeActorDemo.tell("3",ActorRef.noSender());
        becomeActorDemo.tell("4",ActorRef.noSender());
        becomeActorDemo.tell("5",ActorRef.noSender());
        becomeActorDemo.tell("6",ActorRef.noSender());
    }

1.5
receiveA(become方法)>receiveB(become方法)>receiveC(become方法,false)>receiveD(unbecome)>receiveC
become方法的第二个参数默认是true,如果是false就会默认替换Receive为当前的正在处理消息的Receive,如果只有两个Receive时就算写了false但不会替换第一个Recevie也就是不会替换当前的receiveA。

7.Actor(生命周期)的停止,重启,恢复,启动
停止:
当actor被关闭后,其所有的子actor都将被递归地关闭
停止的方法有PoisonPill(不会向父节点发送异常消息),kill(会向父节点发送异常消息),stop

猜你喜欢

转载自blog.csdn.net/qq_40913932/article/details/107962110
今日推荐