Мне нужно вернуться к основному потоку из CompletableFuture<Void>
.
У меня есть сеть CompletableFuture
, которая выполняет асинхронную обработку данных, полученных и вставленных в базу данных SQL.Как только все это будет выполнено, я хочу вернуться в основной поток и выполнить функцию, и я не нашел разумного способа сделать это.
Вызов join()
или get()
блокирует только тот поток, которыйCompletableFuture
работает ... Я не хочу постоянно опрашивать isDone()
.
Я пытался использовать whenComplete()
, но, похоже, он не работает должным образом ...
public static void updatePermIconCache() {
Logger.debug("thread1: " + Thread.currentThread().getId());
hubDatabase.getLobbies().thenAccept(s -> {
for (String lobby : s) {
for (int i = 0; i < 27; i++) {
final int x = i;
hubDatabase.isInPermTable(lobby, i).thenAccept(b -> {
if (!b) return;
hubDatabase.cachePermToJoinTable(lobby, x);
});
}
}
}).whenComplete((v, t) -> registerPanels());
}
Я хочу, чтобы моя функция registerPanels()
была вызвана в главном потоке, но, учитывая, что даже функция updatePermIconCache()
называется асинхронной, наряду с другими функциями, которые определяют, будет ли эта функция вызываться илинет, я не понимаю, как, ну, вернуть его в основной поток.
РЕДАКТИРОВАТЬ: изменен код на это ...
public static void updatePermIconCache() {
Logger.debug("thread1: " + Thread.currentThread().getId());
hubDatabase.getLobbies().thenAccept(s -> {
for (String lobby : s) {
for (int i = 0; i < 27; i++) {
final int x = i;
hubDatabase.isInPermTable(lobby, i).thenAccept(b -> {
if (!b) return;
hubDatabase.cachePermToJoinTable(lobby, x).join();
registerPanels();
});
}
}
});
}
Проблема в ... идентификатор основного потокаравно 21
, в первой строке функции registerPanels()
я печатаю Thread#currentThread#getId()
, и он печатает несколько разных чисел, в диапазоне от 30
до 42
.Он должен печатать 21
, если он запускается в главном потоке, верно?
EDIT: это первый вызываемый метод, который запускается async
public CompletableFuture<Void> calibrate() {
return CompletableFuture.runAsync(() -> {
getLobbies().thenAccept(a -> Arrays.stream(a).forEach(this::createPermToJoinTable));
getLobbies().thenAccept(a -> Arrays.stream(a).forEach(this::createVanishedTable));
});
}
public CompletableFuture<String[]> getLobbies() {
String sql = "SELECT * FROM lobby";
List<String> list = new ArrayList<>();
return queryAsync(r -> {
while(r.next()) {
list.add(r.getString(1));
}
return r;
}, sql).thenApplyAsync(v -> list.toArray(new String[list.size()]));
}
Эти методы изначально вызываются отсюда ...
public static CompletableFuture<Void> addToPerm(String lobby) {
HubDatabase hubDatabase = MinelightHub.getHubDatabase();
return hubDatabase.calibrate().thenRunAsync(() -> {
hubDatabase.addToPermToJoinTable(lobby, 0, "Admin", getDesc(true), Material.WOOL, getData(DyeColor.RED), Permissions.ADMIN, true);
hubDatabase.addToPermToJoinTable(lobby, 1, "Mod", getDesc(false), Material.WOOL, getData(DyeColor.ORANGE), Permissions.MOD, false);
hubDatabase.addToPermToJoinTable(lobby, 2, "Builder", getDesc(false), Material.WOOL, getData(DyeColor.CYAN), Permissions.BUILDER, false);
hubDatabase.addToPermToJoinTable(lobby, 3, "YouTube", getDesc(false), Material.WOOL, getData(DyeColor.RED), Permissions.YOUTUBE, false);
hubDatabase.addToPermToJoinTable(lobby, 9, "JrAdmin", getDesc(false), Material.WOOL, getData(DyeColor.RED), Permissions.JRADMIN, false);
hubDatabase.addToPermToJoinTable(lobby, 10, "JrMod", getDesc(false), Material.WOOL, getData(DyeColor.ORANGE), Permissions.JRMOD, false);
hubDatabase.addToPermToJoinTable(lobby, 11, "Artist", getDesc(false), Material.WOOL, getData(DyeColor.CYAN), Permissions.ARTIST, false);
hubDatabase.addToPermToJoinTable(lobby, 12, "Twitch", getDesc(false), Material.WOOL, getData(DyeColor.PURPLE), Permissions.TWITCH, false);
hubDatabase.addToPermToJoinTable(lobby, 17, "Default", getDesc(false), Material.WOOL, getData(DyeColor.GRAY), Permissions.DEFAULT, false);
hubDatabase.addToPermToJoinTable(lobby, 18, "SrMod", getDesc(false), Material.WOOL, getData(DyeColor.ORANGE), Permissions.SRMOD, false);
hubDatabase.addToPermToJoinTable(lobby, 19, "Trial", getDesc(false), Material.WOOL, getData(DyeColor.ORANGE), Permissions.TRIAL, false);
hubDatabase.addToPermToJoinTable(lobby, 20, "Partner", getDesc(false), Material.WOOL, getData(DyeColor.BLUE), Permissions.PARTNER, false);
hubDatabase.addToPermToJoinTable(lobby, 21, "VIP", getDesc(false), Material.WOOL, getData(DyeColor.GREEN), Permissions.VIP, false);
}).thenRunAsync(InventoryManager::updatePermIconCache);
}
Теперь вы можетевид пути, который необходим, чтобы помочь информировать об этой ситуации.Когда я создаю 'лобби', сначала запускается метод #addToPerm(String lobby)
, хотя таблицы в базе данных SQL необходимо создать, прежде чем я смогу изменить, добавить в него какие-либо данные ... Это то, что (в методе #addToPerm(String lobby)
)) метод #calibrate
делает.Как только он создал лобби, мне нужно заполнить его данными, такими как hubDatabase#addToPermJoinTable()
.После добавления всех этих данных мне нужно обновить локальный кеш InventoryManager#updatePermIconCache()
.После загрузки всего этого кэша мне нужно вернуться в основной поток и вызвать метод #registerPanels()
, так как этот метод использует небезопасный API потока.Я все еще застрял на том, как это сделать ...