vertx内的多线程

时间:2013-08-20 10:23:04

标签: java tcp vert.x

我是vert.x的新手。我正在尝试使用vert.x“NetServer”功能。 http://vertx.io/core_manual_java.html#writing-tcp-servers-and-clients它就像一个魅力。

但是,我还读到“一个Verticle实例严格是单线程的。

如果您创建一个简单的TCP服务器并部署它的单个实例,那么该服务器的所有处理程序总是在同一个事件循环(线程)上执行。“

目前,对于我的实现,我想接收TCP字节流,然后触发另一个组件。但这不应该是Verticle的“start”方法中的阻塞调用。那么,在start方法中编写执行程序是一种好的做法吗?或者vertx会自动处理这种情况。

这是一个片段

public class TCPListener extends Verticle {

    public void start(){

        NetServer server = vertx.createNetServer();

        server.connectHandler(new Handler<NetSocket>() {
            public void handle(NetSocket sock) {
                container.logger().info("A client has connected");
                sock.dataHandler(new Handler<Buffer>() {
                    public void handle(Buffer buffer) {
                        container.logger().info("I received " + buffer.length() + " bytes of data");

                        container.logger().info("I received " + new String(buffer.getBytes()));
                        //Trigger another component here. SHould be done in a sperate thread. 
                        //The previous call should be returned . No need to wait for component response.
                    }
                });
            }
        }).listen(1234, "host");
    }
}

什么应该是使这个非阻塞调用的机制。

3 个答案:

答案 0 :(得分:8)

我认为这不是Vert.x的方法。

更好的方法是正确使用事件总线而不是Executor。让工作人员对总线上的事件做出响应,进行处理,并在总线完成时发出信号。

创建线程违背了使用vert.x的目的。

答案 1 :(得分:1)

最灵活的方法是创建ExecutorService并使用它处理请求。这样可以对工作者的线程模型进行细粒度控制(固定或可变数量的线程,应该在单个线程上连续执行哪些工作等)。

修改后的样本可能如下所示:

public class TCPListener extends Verticle {

    private final ExecutorService executor = Executors.newFixedThreadPool(10);

    public void start(){

        NetServer server = vertx.createNetServer();

        server.connectHandler(new Handler<NetSocket>() {
            public void handle(final NetSocket sock) { // <-- Note 'final' here
                container.logger().info("A client has connected");
                sock.dataHandler(new Handler<Buffer>() {
                    public void handle(final Buffer buffer) { // <-- Note 'final' here

                        //Trigger another component here. SHould be done in a sperate thread. 
                        //The previous call should be returned . No need to wait for component response.
                        executor.submit(new Runnable() {

                            public void run() {
                                //It's okay to read buffer data here
                                //and use sock.write() if necessary
                                container.logger().info("I received " + buffer.length() + " bytes of data");
                                container.logger().info("I received " + new String(buffer.getBytes()));
                            }
                        }
                    }
                });
            }
        }).listen(1234, "host");
    }
}

答案 2 :(得分:0)

正如duffymo提到的创建线程失败了使用vertx的目的。最好的方法是将消息写入eventbus并创建一个新的处理程序来监听来自事件总线的消息。更新了代码以展示此内容。将消息写入&#34; next.topic&#34;主题,并注册了一个处理程序来读取来自&#34; next.topic&#34;话题。

public class TCPListener extends Verticle {

public void start(){

    NetServer server = vertx.createNetServer();

    server.connectHandler(new Handler<NetSocket>() {
        public void handle(NetSocket sock) {
            container.logger().info("A client has connected");
            sock.dataHandler(new Handler<Buffer>() {
                public void handle(Buffer buffer) {
                    String recvMesg = new String(buffer.getBytes());
                    container.logger().info("I received " + buffer.length() + " bytes of data");

                    container.logger().info("I received " + recvMesg);
                    //Writing received message to event bus
                    vertx.eventBus().send("next.topic", recvMesg);
                }
            });
        }
    }).listen(1234, "host");

    //Registering new handler listening to "next.topic" topic on event bus
    vertx.eventBus().registerHandler("next.topic", new Handler<Message<String>() {
       public void handle(Message<String> mesg) {
           container.logger.info("Received message: "+mesg.body());
       }
    };

}
}