1

在查看了他们的官方教程开始使用异步指南之后,我试图了解 Uni 在 Quarkus 框架中的行为。在服务方法中,我做了以下更改

package org.acme.getting.started.async;

import javax.enterprise.context.ApplicationScoped;

import io.smallrye.mutiny.Uni;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


@ApplicationScoped
public class GreetingService {

    ExecutorService executor = Executors.newFixedThreadPool(10, r -> {
        return new Thread(r, "CUSTOM_TASK_EXECUTION_THREAD");
    });


    public Uni<String> greeting(String name) {
        System.out.println("greeting Executing on Thread "+Thread.currentThread().getName());
        return Uni.createFrom().item(ioSimulation(name))
                .emitOn(executor);//Infrastructure.getDefaultExecutor()
    }

    public String ioSimulation(String param){
        System.out.println("ioSimulation Executing on Thread "+Thread.currentThread().getName());
        try {
            Thread.sleep(8000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "hello "+param;

    }

}

然后我测试了 /greeting/{name} 资源,执行根本不是异步的,实际上它在同一个线程中以同步方式执行了所有相关方法。

那么这之间有什么区别

@GET
    @Produces(MediaType.TEXT_PLAIN)
    @Path("/greeting/{name}")
    public Uni<String> greeting(@PathParam String name) {
    }

@GET
    @Produces(MediaType.TEXT_PLAIN)
    @Path("/greeting/{name}")
    public String greeting(@PathParam String name) {
    }

它是如何异步的?请帮助我理解它。

4

3 回答 3

3

问题出在Uni.createFrom().item(ioSimulation(name)). ioSimulation您在创建之前同步调用Uni

您至少应该使用Supplier变体:Uni.createFrom().item(() -> ioSimulation(name)). 那应该有帮助。

于 2021-05-10T21:53:55.840 回答
3

除了@Ladicek 的回答,我相信你想使用runSubscriptionOn而不是emitOn. 请参阅https://smallrye.io/smallrye-mutiny/guides/emit-subscription作为参考。

于 2021-05-11T05:31:35.690 回答
1

以上两个答案都是正确的。我对服务类进行了一些更改,并将ioSimulation(String param)方法卸载到自定义线程池。最终解决方案如下

public class GreetingService {

    ThreadFactory threadFactory = new NameableThreadFactory("CUSTOM_TASK_EXECUTION_THREAD");
    ExecutorService executor = Executors.newFixedThreadPool(10, threadFactory);

    public Uni<String> greeting(String name) {
        System.out.println("greeting Executing on Thread "+Thread.currentThread().getName());
        return Uni.createFrom().item(()->ioSimulation(name))
                .runSubscriptionOn(executor);//Infrastructure.getDefaultExecutor()
    }


    public String ioSimulation(String param){
        System.out.println("ioSimulation Executing on Thread "+Thread.currentThread().getName());
        try {
            Thread.sleep(8000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "hello "+param;

    }
}

--更新--

emitOn(Executor executor)如果您传入方法,也将异步工作supplieritem但方法略有不同,我认为在试验时Uni是我的回购,以防有人感兴趣。

于 2021-05-11T13:35:58.923 回答