当前位置: 首页 > 知识库问答 >
问题:

Vertx,多线程的工作原理

支彭亮
2023-03-14

在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将任务放入队列,稍后执行,

那么工人顶点,我们有另一个线程池,默认情况下等于20,当我们使用以下方法:vertx.execute块()我们使用这个池的线程。

我的理解正确吗?

(PS)根据下面的asnwer,使用handler阻塞代码和使用handler但使用execute阻塞的阻塞代码没有区别

//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个答案

步博涉
2023-03-14

维特。x维护两个线程池。

一个是事件循环线程。默认情况下,每个内核有两个事件循环线程。在4核机器上,将有8个事件循环线程。每个非阻塞代码都在事件循环上运行。如果部署多个垂直条,它们通常均匀分布在事件循环线程上。重要的是,代码不能阻塞,否则同一事件循环中的所有其他代码都会被阻塞。

另一个线程池是工作池(默认大小为20,但这是可配置的,参见https://vertx.io/docs/apidocs/io/vertx/core/VertxOptions.html#DEFAULT_WORKER_POOL_SIZE),这是一种“经典”线程。当您调用执行阻塞时,这段代码被分派到工作池的线程,这样它就不会阻塞事件循环。

当执行阻塞时,您提供了两个处理程序,一个执行阻塞代码,在工作线程上运行,另一个接收结果,在事件循环(调用线程,如果您愿意)上运行

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部件,因此您不必处理这个问题。所以,是的,它基本上与在第一个,在一个执行阻塞语句中的Block ingHandler中编写自己的JDBC访问代码相同。您也可以在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

 类似资料:
  • Vertx使用一个辅助线程来执行select语句,以避免阻塞事件循环线程,但是在这种情况下,每个sql查询都需要一个单独的线程来执行。但是如果Vertx不使用任何单独线程来执行查询呢?在这种情况下,事件循环如何知道结果何时来自DB呢?使用线程就很简单了,事件循环可以检查jdbc查询使用的线程的当前状态,如果状态准备就绪,就意味着事件循环应该执行回调 我说得对吗?

  • 我是vert的新手。x、 我在尝试垂直。x“NetServer”功能。http://vertx.io/core_manual_java.html#writing-tcp服务器和客户端,它的工作方式很有魅力。 然而,我也读到“verticle实例严格来说是单线程的。 如果您创建一个简单的TCP服务器并部署它的单个实例,那么该服务器的所有处理程序始终在同一个事件循环(线程)上执行。” 目前,对于我的实

  • 我有4-5个工作线程处理大型消息队列。我还有另一段代码,它使用2-3个worker运行。我想在处理大型消息队列时阻止所有其他工作者。 我正在使用JDK6和Jms 编辑: 队列进程工作者从未终止。当没有消息时,它们阻塞队列。这些工作者由执行器线程池管理,如果我使用读写锁,其中一个工作者也会被阻塞。此外,如果使用循环屏障,那么我必须终止线程,以便重新传递阻塞的第二个进程。由于工作者是由线程池管理的,所

  • 问题内容: 最近,我正在阅读一个教程,其中遇到了一条声明: “Java语言规范保证了读取或写入的变量是一个原子操作(除非该变量的类型的或)类型的操作变量或者是只有当它们与申报原子的关键字。” 或提供类似的方法,并且其是原子的。 我对以上声明感到有些困惑。.请您澄清一下 何时使用 或 使用类。 问题答案: 否则(与作为一个)是一个原子操作。但是执行操作不是原子操作,因为它需要读取a的值,递增和写入a

  • 基于文档https://netty . io/4.1/API/io/netty/channel/channel pipeline . html:< br > //告诉管道在与I/O线程不同的线程中运行MyBusinessLogicHandler的事件处理程序方法 //,这样I/O线程就不会被 //阻塞,这是一项耗时的任务。 //如果您的业务逻辑是完全异步的或很快就完成了,您不需要指定一个组。 pi

  • 原子操作是否足够安全,可以在多线程应用程序中使用它,而不会导致竞争条件和其他并发问题?假设我们不担心可见性(我们从CPU读取/写入所有内容)。