如何在可完成的将来异步运行方法

时间:2019-07-20 10:35:13

标签: java sql asynchronous completable-future

我正在运行Minecraft服务器,并且正在创建一个插件,当玩家执行某些命令时,该插件即可。它获取它们在sql数据库中拥有的“硬币”数量。但是,使用CompletableFuture异步运行SQL方法时遇到麻烦。我的CoinUsable类一直处于阻塞状态,而我的main和sql类也一直处于阻塞状态。我对异步编程非常陌生。

我只需要找出一种在CoinUsableSQLManager类中异步运行我的方法的方法。

玩家执行命令的主要班级。




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类也阻塞了,这意味着一个玩家必须等待另一个玩家的请求通过才能发送。

1 个答案:

答案 0 :(得分:1)

使用CompletableFuture<Void> runAsync(Runnable runnable)

  

返回一个新的CompletableFuture,它由运行给定操作的ForkJoinPool.commonPool()中运行的任务异步完成。

还有CompletableFuture<U> supplyAsync(Supplier<U> supplier)

  

返回一个新的CompletableFuture,它由在ForkJoinPool.commonPool()中运行的任务异步完成,并具有通过调用给定的Supplier所获得的值。

对于使用supplyAsyncrunAsync进行异步执行,您使用CompletableFuture的方式是错误的

CoinUsable / Manager类:使用supplyAsyncrunAsync方法来调用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