It is possible to run things asynchronly (in a other thread) and go back to synchronous (/ callbacks)?
I need this because I want to do database requests and one requests took 0.2 - 1.2ms.
My implementation in java:
And a example use of the queue:
I need this because I want to do database requests and one requests took 0.2 - 1.2ms.
My implementation in java:
package tv.rewinside.database.bukkit.util;
import com.google.common.collect.Queues;
import java.util.Queue;
import java.util.logging.Level;
import tv.rewinside.database.bukkit.DatabasePlugin;
public class DatabaseQueue extends Thread {
private final Queue<Runnable> runnables = Queues.newConcurrentLinkedQueue();
public DatabaseQueue() {
super("Database Queue");
this.setDaemon(true);
}
public synchronized void addRunnable(Runnable runnable) {
this.runnables.add(runnable);
this.notify();
}
private synchronized void blockCurrentThread() {
try {
while (this.runnables.isEmpty()) {
this.wait();
}
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
public int getCount() {
return this.runnables.size();
}
@Override
public void run() {
while (!this.isInterrupted()) {
this.blockCurrentThread();
while (!this.runnables.isEmpty()) {
try {
this.runnables.poll().run();
} catch (Exception ex) {
DatabasePlugin.getInstance().getLogger().log(Level.WARNING, "Exception while execute database task", ex);
}
}
}
}
}
public interface DatabaseCallback<T> {
public void run(T result);
}
And a example use of the queue:
public void getPlayer(final String uuid, final DatabaseCallback<DatabasePlayer> callback) {
DatabasePlayer dbPlayer = this.cachedPlayers.get(uuid);
if (dbPlayer != null) {
callback.run(dbPlayer);
return;
}
// Load player -> Async
this.plugin.getQueue().addRunnable(new Runnable() {
@Override
public void run() {
DatabaseCache.this.syncCallbackCall(callback, DatabaseCache.this.loadPlayer(uuid));
}
});
}
private DatabasePlayer loadPlayer(String uuid) {
DatabasePlayer dbPlayer = this.plugin.getConnection().getPlayer(uuid);
if (dbPlayer == null) return null;
this.cachedPlayers.put(uuid, dbPlayer);
this.cachedPlayersFromName.put(dbPlayer.getLastName(), dbPlayer);
return dbPlayer;
}
private <T> void syncCallbackCall(final DatabaseCallback<T> callback, final T arg) {
if (Bukkit.isPrimaryThread()) {
callback.run(arg);
return;
}
Bukkit.getScheduler().runTask(this.plugin, new Runnable() {
@Override
public void run() {
callback.run(arg);
}
});
}


If we could create a new thread for a certain function, then it should be really easy to make WorldEdit use it