即使在使用 Vert.x 和 Log4j2 将“isThreadContextMapInheritable”设置为 true 后也没有获取 ThreadContext 值

Posted

技术标签:

【中文标题】即使在使用 Vert.x 和 Log4j2 将“isThreadContextMapInheritable”设置为 true 后也没有获取 ThreadContext 值【英文标题】:Not getting ThreadContext values even after setting "isThreadContextMapInheritable" to true, using Vert.x and Log4j2 【发布时间】:2021-03-12 02:36:23 【问题描述】:

我正在使用 Vertx 和 Log4j2。

这是Remote.java的代码

public class Remote extends AbstractVerticle 

    @Override
    public void start() throws Exception 
        System.setProperty("isThreadContextMapInheritable", "true");
        ThreadContext.put("1", "Company");
        ThreadContext.put("2", "Sector");
        ThreadContext.put("3", "Address");
        ArrayList<String> arrayList = new ArrayList<>();
        for (int i = 1; i < 4; i++) 
            arrayList.add(String.valueOf(i));
        
        arrayList.parallelStream().forEach(s -> 
            System.out.println("Key " + s + " Value is " + ThreadContext.get(s) + " Name: " + Thread.currentThread().getName());
        );
        System.out.println("After parallelStream");
    

这是我的StartVerticle.java代码

public class StartVerticle 

    public static void main(String[] args) 
        Vertx vertx = Vertx.vertx();
        vertx.deployVerticle(new Remote());
    

当我运行上面的代码时我的输出是

Key 2 Value is Sector Name: vert.x-eventloop-thread-0
Key 1 Value is null Name: ForkJoinPool.commonPool-worker-3
Key 3 Value is null Name: ForkJoinPool.commonPool-worker-5
After parallelStream

您能帮我获得以下输出吗?

Key 2 Value is Sector Name: vert.x-eventloop-thread-0
Key 1 Value is Company Name: ForkJoinPool.commonPool-worker-3
Key 3 Value is Address Name: ForkJoinPool.commonPool-worker-5
After parallelStream

我还打印了线程名称以供参考。 在不使用 Vertx 的情况下,将isThreadContextMapInheritable 设置为true 后,我能够打印ThreadContext 中的所有内容。

【问题讨论】:

【参考方案1】:

VertxParallel Stream 都使用 Fork Join Common Pool。只有在公共池初始化之前设置的线程上下文值在子线程中可用。


即使没有 Vertx,在第一个并行流之后设置的 ThreadContext 值在子线程中也将不可用。例如,

public static void main(String[] args) throws Exception 
    System.setProperty("isThreadContextMapInheritable", "true");
    IntStream.range(0, 5)
             .parallel()
             .forEach(System.out::println);
    ThreadContext.put("1", "Company");
    ThreadContext.put("2", "Sector");
    ThreadContext.put("3", "Address");

    ArrayList<String> arrayList = new ArrayList<>();
    for (int i = 1; i < 4; i++) 
        arrayList.add(String.valueOf(i));
    
    arrayList.parallelStream()
             .forEach(s -> 
                 System.out.println("Key " + s + " Value is " + ThreadContext.get(s) + " Name: " + Thread.currentThread()
                                                                                                         .getName());
             );

这会打印出来

Key 1 Value is null Name: ForkJoinPool.commonPool-worker-5
Key 3 Value is null Name: ForkJoinPool.commonPool-worker-1
Key 2 Value is Sector Name: main

在我们的例子中,公共池在Vertx 启动时被初始化。此时,没有设置线程上下文值。 所以一种选择是在启动vertx之前在main()中设置线程上下文。

public static void main(String[] args) 
    System.setProperty("isThreadContextMapInheritable", "true");
    ThreadContext.put("1", "Company");
    ThreadContext.put("2", "Sector");
    ThreadContext.put("3", "Address");
    Vertx vertx = Vertx.vertx();
    vertx.deployVerticle(new Remote());

产生输出,

Key 2 Value is Sector Name: vert.x-eventloop-thread-0
Key 3 Value is Address Name: ForkJoinPool.commonPool-worker-2
Key 1 Value is Company Name: ForkJoinPool.commonPool-worker-1
After parallelStream

【讨论】:

谢谢。但是我的应用程序在创建 vertx 实例后初始化值。有没有办法从 ThreadContext 中获取值,只是从我在代码中使用它的方式?

以上是关于即使在使用 Vert.x 和 Log4j2 将“isThreadContextMapInheritable”设置为 true 后也没有获取 ThreadContext 值的主要内容,如果未能解决你的问题,请参考以下文章

在 vert.x 中获取用户并验证 JWT 令牌

使用Vert.x构建Web服务器和消息系统

13.始源之地:Vert.x集成

Vert.x 3 和微服务

如何将 CompletableFuture 转换为 Vert.X Future

如何使用 vert.x eventbus 在 openfaas 函数之间进行通信