Избегание закрепления виртуального потока путем перемещения кода для выполнения в потоке платформы.JAVA

Программисты JAVA общаются здесь
Ответить
Anonymous
 Избегание закрепления виртуального потока путем перемещения кода для выполнения в потоке платформы.

Сообщение Anonymous »

Я переношу свое приложение Spring Boot на виртуальные потоки с платформенных.
В целом все работает нормально, никакого закрепления не происходит. Но для некоторых запросов может быть операция, которая приводит к закреплению (из-за операции блокировки внутри синхронизированного блока), и я хочу этого избежать. Если я этого не сделаю, я могу оказаться в ситуации, когда все операторы связи будут закреплены и не останется потока платформы для обслуживания запроса.
Операция, которая приводит к закреплению, представляет собой часть сторонней библиотеки. Ожидая исправления, которое позволит мне выполнять код библиотеки без закрепления, я планирую использовать следующий подход:
Отправьте код, который закрепляет носитель виртуального потока, службе исполнителя. (при поддержке потоков платформы) и немедленно вызвать .get() (из виртуального потока) в CompletableFuture, который я получу от исполнителя.
Отредактировано: Вот демонстрационный код (Spring Boot)

Код: Выделить всё

import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

import java.time.Instant;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@Component
class AppRunner implements ApplicationRunner {

private final Object monitor = new Object();
private final ExecutorService executorService;

public AppRunner() {
this.executorService = Executors.newFixedThreadPool(2);
}

@Override
public void run(ApplicationArguments args) {
String parallelismNum = System.getProperty("jdk.virtualThreadScheduler.parallelism");
System.out.println("jdk.virtualThreadScheduler.parallelism is set to: " + parallelismNum);
try (var virtualExecutor = Executors.newVirtualThreadPerTaskExecutor()) {
for (int taskId = 0; taskId < 100; taskId++) {
final int taskIdentifier = taskId;
System.out.println("Submitting the task to executor: " + taskIdentifier);
virtualExecutor.submit(() -> simpleLongOperation(taskIdentifier));
/**
* If I submit the following instead of pinningOperationOnPlatform,
* My simpleLongOperation would be waiting for a carrier to unpin
*/
//                virtualExecutor.submit(() -> pinningOperation(taskIdentifier));
virtualExecutor.submit(() -> pinningOperationOnPlatform(taskIdentifier));
}
}
}

/**
* This runs the pinning operation on a platform thread but awaits on the virtual.
* So no pinning is actually happening.
*/
private void pinningOperationOnPlatform(int id) {
try {
executorService.submit(() -> pinningOperation(id))
.get();
} catch (Exception e) {
throw new RuntimeException(e);
}
}

private void simpleLongOperation(int id) {
System.out.println("\tSIMPLE Start operation " + id + " : " + Instant.now());
sleep(1_000);
System.out.println("\tSIMPLE Complete operation " + id + " : " + Instant.now());
}

private void pinningOperation(int id) {
System.out.println("PINNING Start operation " + id + " : " + Instant.now());
synchronized (monitor) {
sleep(5_000);
}
System.out.println("PINNING Complete pinning operation " + id + " : " + Instant.now());
}

private void sleep(long millis) {
try {
Thread.sleep(1_000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}

Насколько я понимаю, операция теперь может ждать входа в синхронизированный блок в потоке пула исполнителя, но поскольку метод .get() вызывается из виртуального потока, их оператор будет свободен после завершения операции. Теперь кажется, что я ограничиваю свой параллелизм размером пула потоков, который исполнитель использует для перемещения операции закрепления в потоке платформы для выполнения, но только для (редких) запросов, которые требуют выполнения операции.
На мой взгляд, это не плохо скажется на производительности приложения. Верны ли мои предположения или я что-то упускаю?


Подробнее здесь: https://stackoverflow.com/questions/787 ... orm-thread
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «JAVA»