I am trying to understand the behavior of Uni in Quarkus framework, after checking out their official tutorial getting started with async guide . In the service method I have made the following changes
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;
}
}
Then I have tested the /greeting/{name} resource, the execution was not async at all, in fact it executed all related methods within the same thread and in synchronous manner.
then what would be the difference between
@GET
@Produces(MediaType.TEXT_PLAIN)
@Path("/greeting/{name}")
public Uni<String> greeting(@PathParam String name) {
}
and
@GET
@Produces(MediaType.TEXT_PLAIN)
@Path("/greeting/{name}")
public String greeting(@PathParam String name) {
}
and how is it asynchronous? please help me to understand it.
The problem is in Uni.createFrom().item(ioSimulation(name))
. You synchronously call ioSimulation
before the Uni
is created.
You should at least use the Supplier
variant: Uni.createFrom().item(() -> ioSimulation(name))
. That should help.
In addition to @Ladicek answer, I believe you want to use runSubscriptionOn
and not emitOn
. See https://smallrye.io/smallrye-mutiny/guides/emit-subscription as reference.
both the answers above are correct. I made some changes in service class and ioSimulation(String param)
method was offloaded to the custom thread pool. The final solution is given below
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;
}
}
-- update --
emitOn(Executor executor)
will also works asynchronously if you pass supplier
in item
method but the approach is slightly different, I have figured that while experimenting with Uni
, this is my repo, incase if anyone is interested.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.