我正在运行Minecraft
服务器,并且正在创建一个插件,当玩家执行某些命令时,该插件即可。它获取它们在sql
数据库中拥有的“硬币”数量。但是,使用CompletableFuture
异步运行SQL方法时遇到麻烦。我的CoinUsable
类一直处于阻塞状态,而我的main和sql类也一直处于阻塞状态。我对异步编程非常陌生。
我只需要找出一种在CoinUsable
和SQLManager
类中异步运行我的方法的方法。
玩家执行命令的主要班级。
CompletableFuture<Integer> cf = CoinUsable.getPlayerCoins(player);
cf.thenAcceptAsync((value) -> {
player.sendMessage(ChatColor.GRAY + "You own " + ChatColor.GOLD + value + ChatColor.GRAY + " coins");
});
我的CoinUsable / Manager类
public CompletableFuture<Integer> getPlayerCoins(Player p) {
return SQL.getPlayerBits(p);
}
public CompletableFuture<Void> addPlayerBits(Player p, int bitAmount) {
SQL.addBits(p, bitAmount);
return null;
}
public CompletableFuture<Void> removePlayerBits(Player p, int bitAmount) {
SQL.removeBits(p, bitAmount);
return null;
}
我的SQLManager类
public CompletableFuture<Integer> getPlayerBits(Player p) {
String queryStr = "SELECT Coins FROM PlayerData WHERE PlayerUID=?";
try {
Connection conn = getConn();
PreparedStatement st = conn.prepareStatement(queryStr);
st.setString(1, p.getUniqueId().toString());
ResultSet rs = st.executeQuery();
rs.next();
Integer amount = (Integer) rs.getInt("Coins");
conn.close();
return CompletableFuture.completedFuture(amount);
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
public CompletableFuture<Void> addBits(Player p, int bitAmount) {
String queryStr = "UPDATE PlayerData SET Coins = Coins + ? WHERE PlayerUID=?";
try {
Connection conn = getConn();
PreparedStatement ps = conn.prepareStatement(queryStr);
ps.setInt(1, bitAmount);
ps.setString(2, p.getUniqueId().toString());
ps.executeUpdate();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
return CompletableFuture.completedFuture(null);
}
public CompletableFuture<Void> removeBits(Player p, int bitAmount) {
String queryStr = "UPDATE PlayerData SET Coins = Coins - ? WHERE PlayerUID=?";
try {
Connection conn = getConn();
PreparedStatement ps = conn.prepareStatement(queryStr);
ps.setInt(1, bitAmount);
ps.setString(2, p.getUniqueId().toString());
ps.executeUpdate();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
return CompletableFuture.completedFuture(null);
}
}
我的主类正在阻止,这导致整个服务器滞后。同样,我的CoinUsable类也阻塞了,这意味着一个玩家必须等待另一个玩家的请求通过才能发送。
答案 0 :(得分:1)
使用CompletableFuture<Void> runAsync(Runnable runnable)
返回一个新的CompletableFuture,它由运行给定操作的ForkJoinPool.commonPool()中运行的任务异步完成。
还有CompletableFuture<U> supplyAsync(Supplier<U> supplier)
返回一个新的CompletableFuture,它由在ForkJoinPool.commonPool()中运行的任务异步完成,并具有通过调用给定的Supplier所获得的值。
对于使用supplyAsync
和runAsync
进行异步执行,您使用CompletableFuture
的方式是错误的
CoinUsable / Manager类:使用supplyAsync
和runAsync
方法来调用SQLManager
类方法,这样getPlayerBits
,{{1 }}和addBits
将异步执行
removeBits
我的SQLManager类:在public CompletableFuture<Integer> getPlayerCoins(Player p) {
return CompletableFuture.supplyAsync(()->SQL.getPlayerBits(p));
}
public CompletableFuture<Void> addPlayerBits(Player p, int bitAmount) {
return CompletableFuture.runAsync(()->SQL.addBits(p, bitAmount));
}
public CompletableFuture<Void> removePlayerBits(Player p, int bitAmount) {
return CompletableFuture.runAsync(()->SQL.removeBits(p, bitAmount));
}
类中,只需保留具有各自返回类型的普通方法即可
SQLManager