Thread vertx-eventloop-thread-3 has been blocked for 20458 ms

快速解决:

WorkerExecutor executor = vertx.createSharedWorkerExecutor("my-worker-pool");
executor.executeBlocking(future -> {
  // 调用一些需要耗费显著执行时间返回结果的阻塞式API
  String result = someAPI.blockingMethod("hello");
  future.complete(result);
}, res -> {
  System.out.println("The result is: " + res.result());
});

了解更多:

https://vertxchina.github.io/vertx-translation-chinese/core/Core.html

如果您的应用程序没有响应,可能这是一个迹象,表明您在某个地方阻塞了Event Loop。为了帮助您诊断类似问题,若 Vert.x 检测到 Event Loop 有一段时间没有响应,将会自动记录这种警告。若您在日志中看到类似警告,那么您需要检查您的代码。比如:

Thread vertx-eventloop-thread-3 has been blocked for 20458 ms

Vert.x 还将提供堆栈跟踪,以精确定位发生阻塞的位置。

如果想关闭这些警告或更改设置,您可以在创建 Vertx 对象之前在 VertxOptions 中完成此操作。

运行阻塞式代码

在一个完美的世界中,不存在战争和饥饿,所有的API都将使用异步方式编写,兔兔和小羊羔将会在阳光明媚的绿色草地上手牵手地跳舞。

但是……真实世界并非如此(您最近看新闻了吧?)

事实是,很多,也非所有的库,特别是在JVM生态系统中有很多同步API,这些API中许多方法都是阻塞式的。一个很好的例子就是 JDBC API,它本质上是同步的,无论多么努力地去尝试,Vert.x都不能像魔法小精灵撒尘变法一样将它转换成异步API。

我们不会将所有的内容重写成异步方式,所以我们为您提供一种在 Vert.x 应用中安全调用"传统"阻塞API的方法。

如之前讨论,您不能在 Event Loop 中直接调用阻塞式操作,因为这样做会阻止 Event Loop 执行其他有用的任务。那您该怎么做?

可以通过调用 executeBlocking 方法来指定阻塞式代码的执行以及阻塞式代码执行后处理结果的异步回调。

vertx.executeBlocking(future -> {
  // 调用一些需要耗费显著执行时间返回结果的阻塞式API
  String result = someAPI.blockingMethod("hello");
  future.complete(result);
}, res -> {
  System.out.println("The result is: " + res.result());
});

默认情况下,如果 executeBlocking 在同一个上下文环境中(如:同一个 Verticle 实例)被调用了多次,那么这些不同的 executeBlocking 代码块会 顺序执行(一个接一个)。

若您不需要关心您调用 executeBlocking 的顺序,可以将 ordered 参数的值设为 false。这样任何executeBlocking 都会在 Worker Pool 中并行执行。

另外一种运行阻塞式代码的方法是使用 Worker Verticle

一个 Worker Verticle 始终会使用 Worker Pool 中的某个线程来执行。

默认的阻塞式代码会在 Vert.x 的 Worker Pool 中执行,通过 setWorkerPoolSize 配置。

可以为不同的用途创建不同的池:

WorkerExecutor executor = vertx.createSharedWorkerExecutor("my-worker-pool");
executor.executeBlocking(future -> {
  // 调用一些需要耗费显著执行时间返回结果的阻塞式API
  String result = someAPI.blockingMethod("hello");
  future.complete(result);
}, res -> {
  System.out.println("The result is: " + res.result());
});

Worker Executor 在不需要的时候必须被关闭:

executor.close();

当使用同一个名字创建了许多 worker 时,它们将共享同一个 pool。当所有的 worker executor 调用了close 方法被关闭过后,对应的 worker pool 会被销毁。

如果 Worker Executor 在 Verticle 中创建,那么 Verticle 实例销毁的同时 Vert.x 将会自动关闭这个 Worker Executor。

Worker Executor 可以在创建的时候配置:

int poolSize = 10;

// 2分钟
long maxExecuteTime = 120000;

WorkerExecutor executor = vertx.createSharedWorkerExecutor("my-worker-pool", poolSize, maxExecuteTime);

请注意:这个配置信息在 worker pool 创建的时候设置。

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

风铃峰顶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值