My first solution, if I had control over TaskManager, would be to change it such that it also passed a UUID parameter to the callback or had another method of control - then using the result of the method would be moot.
However, if I did not then..
(Edit: I've been informed that the correct way to handle this in Java 8 is with a CompletableFuture - see Stuarts's answer.)
Another approach is to use a "mutable reference wrapper", like Holder<T> (or T[] or make your own), to emulate mutable bindings. Then,
Holder<UUID> idRef = new Holder<UUID>(); // Effectively final
idRef.value = TaskManager.newRepeatingTask(() -> {
for (int i = 0; i < profileButtons.length; i++) {
GuiButton button = profileButtons[i];
button.move(-1, 0);
}
toMove--;
if (toMove == 0) {
UUID id = idRef.value;
TaskManager.cancelTask(id);
}
}, 30L, 0L);
Like the Runnable-with-UUID approach, this also suffers from a potential race condition between the assignment of the ID and the potential usage inside the lambda/Runnable if the task is run on a different thread. (If run later on the same thread then synchronization issues need not apply; and if run immediately on the same thread then the UUID is never observable inside the lambda.)
Applying a shared-synchronization both outside/wrapping the method call itself (and inside around the applicable code) should take care of that unless the Runnable is called immediately. Synchronization, or equivalent, should be done anyway for guaranteed visibility reasons (even if there is no "race condition") if such an approach is taken and the task may be executed on a different thread.
Holder<UUID> idRef = new Holder<UUID>();
synchronized(idRef) {
idRef.value = TaskManager.newRepeatingTask(() -> {
for (int i = 0; i < profileButtons.length; i++) {
GuiButton button = profileButtons[i];
button.move(-1, 0);
}
toMove--;
if (toMove == 0) {
// id: "The variable may not have been initialized"
synchronized(idRef) {
UUID id = idRef.value;
TaskManager.cancelTask(id);
}
}
}, 30L, 0L);
}
TaskManagerbelong to?TaskManageris in my utils, and I have complete control of it. What this information was needed for I have no idea. The problem is officially solved now.