In Vertx official docs I read the following paragraph
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.
And in article about 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.
As I understand, please correct my if I write something wrong, Vertx works in the following way:
When we provide a handler to blocking code, vertx put one thread(not event loop) to this code from thread pool that equals to the number of cores for example I have 4 cores, and event loop check the state of this thread after each iteration and if it ready execute handler that relate to this blocking code, when all 4 cores are busy vertx put task to the queue to be executed later,
What about worker verticle, we have another thread pool that by default is equal to 20, when we use following method: vertx.executeBlocking()
we use thread from this pool.
Is my understanding correct?
(PS) According to the asnwer below there is no difference between blocking code with handler and blocking code with handler but using 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;
}
}
//worker thread
vertx.executeBlocking(e->{},handler->{});
Is my understanding right, both codes use worker thread under the hood?
Verticles run in single thread mode. That means, that a verticle is only ever executed by a single thread, and always by the same thread. That means that you will never have to think about multithreading inside your verticle (unless you yourself start other threads which your verticle communicates with etc).
Vert. x is not single threaded like node. js.
The idea is instead of having a new for serving each HTTP request, same thread is used which you have blocked by your long running task. The goal of event loop is to save the time involved in context switching from one thread to another thread and utilize the ideal CPU time when a task is using IO/Network activities.
A Vert. x event-bus is a light-weight distributed messaging system which allows different parts of your application, or different applications and services to communicate with each in a loosely coupled way. An event-bus supports publish-subscribe messaging, point-to-point messaging and request-response messaging.
Vert.x maintains two thread-pools.
One with the event-loop threads. Which are by default two event-loop threads per core. On a 4 core machine, you'll have 8 event-loop threads. Every non blocking code is run on the event loops. If you deploy multiple verticles, they usually evenly distributed on the event loop threads. It's crucial the code doesn't block otherwise all other code on the same event loop is blocked.
The other thread pool is the worker pool (the default size is 20, but that's configurable, see https://vertx.io/docs/apidocs/io/vertx/core/VertxOptions.html#DEFAULT_WORKER_POOL_SIZE), which is kind of "classic" threading. When you invoke executeBlocking
the piece of code is dispatched to a thread of the worker pool so it doens't block the event loop.
When you execute blocking, you provide two handlers, one that executes the blocking code, this is run on the worker thread, and the other - which receives the result - is run on the event loop (the caller thread, if you like)
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());
});
Regarding your added question, you're using the Vert.x JDBC client here, which
under the hood runs the blocking JDBC parts on the worker thread, so you don't have to take care of this. So, yes, it basically the same as writing your own JDBC access code inside the first, blockingHandler in an executeBlocking
statement. You could see it in the code of the Vert.x JDBC client as well: https://github.com/vert-x3/vertx-jdbc-client/blob/c83138c00390777f3d17ac492f09203e9e92284d/src/main/java/io/vertx/ext/jdbc/impl/actions/AbstractJDBCAction.java#L66
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With