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); } }); }