Vertx,多线程如何工作

6
在Vertx官方文档中,我读到了以下段落。
   If a result can be provided immediately, it will be returned immediately, otherwise you will usually provide a handler to receive events some time later.
Because none of the Vert.x APIs block threads that means you can use Vert.x to handle a lot of concurrency using just a small number of threads.

关于 Reactor 的文章:

Vert.x works differently here. Instead of a single event loop, each Vertx instance maintains several event loops. By default we choose the number based on the number of available cores on the machine, but this can be overridden.

据我所了解,如果我写错了,请纠正。Vertx的工作方式如下:
当我们为阻塞代码提供一个处理程序时,vertx从线程池中选择一个线程(不是事件循环)来运行此代码,线程池的数量等于例如我有4个核心,事件循环在每次迭代后检查此线程的状态,如果它已准备好执行与此阻塞代码相关的处理程序,则执行该处理程序,当所有4个核心都正在忙碌时,vertx将任务放到队列中以便稍后执行。
至于工作 verticle,我们有另一个线程池,默认情况下相等于20,当我们使用以下方法:vertx.executeBlocking()时,我们使用该池中的线程。
我的理解正确吗?
(PS) 根据下面的回答,使用处理程序和使用execute blocking的处理程序的阻塞代码之间没有区别。
//jdbc
    connection.execute("insert into test values (1, 'Hello'), (2, 'World')", insert -> {

              // query some data with arguments
              connection.queryWithParams("select * from test where id = ?", new JsonArray().add(2), rs -> {
                if (rs.failed()) {
                  System.err.println("Cannot retrieve the data from the database");
                  rs.cause().printStackTrace();
                  return;
                }
    }

//工作线程

vertx.executeBlocking(e->{},handler->{});

我的理解是否正确,这两个代码都在后台使用工作线程?

1个回答

8

Vert.x有两个线程池。

一个是事件循环线程池,默认情况下每个核心有两个事件循环线程,在4核机器上,您将拥有8个事件循环线程。所有非阻塞代码都在事件循环上运行。如果您部署了多个Verticle,则它们通常会均匀分布在事件循环线程上。关键是代码不要阻塞,否则同一事件循环上的所有其他代码都会被阻塞。

另一个线程池是工作线程池(默认大小为20,但可以配置,参见https://vertx.io/docs/apidocs/io/vertx/core/VertxOptions.html#DEFAULT_WORKER_POOL_SIZE),这有点像“传统”的线程。当调用executeBlocking时,代码片段被分派到工作池的线程中,以便不会阻塞事件循环。

执行阻塞操作时,您需要提供两个处理程序,一个执行阻塞代码,这在工作线程上运行,而另一个-接收结果-在事件循环(调用者线程)上运行。

vertx.executeBlocking(fut -> {
  //blocking code, run on the worker thread
  fut.complete("my result");
}, res -> {
  //non blocking code running on the event loop thread
  System.out.println(res.result());
});

关于您的附加问题,您在此处使用的是Vert.x JDBC客户端,在底层上运行阻塞的JDBC部分在工作线程上,因此您不必担心这个问题。因此,是的,它基本上与在第一个blockingHandler中编写自己的JDBC访问代码相同,并将其放在executeBlocking语句中。您也可以在Vert.x JDBC客户端的代码中看到它:https://github.com/vert-x3/vertx-jdbc-client/blob/c83138c00390777f3d17ac492f09203e9e92284d/src/main/java/io/vertx/ext/jdbc/impl/actions/AbstractJDBCAction.java#L66

像JDBC select或insert这样的处理程序如何阻止调用呢?例如,我们进行插入查询并添加一个处理程序,事件循环如何知道何时完成插入操作? - Almas Abdrazak
对于所有阻塞执行:阻塞处理程序在工作线程上运行,一旦完成,将结果放入future中,future传递给resultHandler,后者在事件循环上运行,这样事件循环就会得到通知。顺便说一下,Vertx JDBC客户端以阻塞方式为您执行jdbc调用,因此您不必自己处理它。 - Gerald Mücke

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接