如何 运行 方法与可完成的未来异步

How to run methods asynchronously with completable future

我正在 运行 设置一个 Minecraft 服务器,我正在创建一个插件,当玩家执行某个命令时。它获取 'coins' 他们在 sql 数据库中的数量。然而,我 运行 遇到麻烦使用 CompletableFuture 到 运行 我的 SQL 异步方法。我的 CoinUsable class 一直阻塞,我的 main 和 sql class 也是。我对异步编程很陌生。

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

我的主要class玩家执行命令的地方。




CompletableFuture<Integer> cf = CoinUsable.getPlayerCoins(player);
                        cf.thenAcceptAsync((value) -> {
                            player.sendMessage(ChatColor.GRAY + "You own " + ChatColor.GOLD + value + ChatColor.GRAY + " coins");
                        });


我的CoinUsable/Managerclass


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

我的SQL经理class

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

我的主 class 正在阻塞,导致整个服务器延迟。还有我的 CoinUsable class 它也阻塞了,这意味着玩家必须等待另一个玩家请求通过才能发送他的请求。

使用CompletableFuture<Void> runAsync(Runnable runnable)

Returns a new CompletableFuture that is asynchronously completed by a task running in the ForkJoinPool.commonPool() after it runs the given action.

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

Returns a new CompletableFuture that is asynchronously completed by a task running in the ForkJoinPool.commonPool() with the value obtained by calling the given Supplier.

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

CoinUsable/Manager class : 使用 supplyAsyncrunAsync 方法调用 SQLManager class 方法,以便 getPlayerBitsaddBitsremoveBits 将异步执行

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 class :SQLManager class 中只保持方法与各自 return 类型的正常

public 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 amount;
    } catch (SQLException e) {
        e.printStackTrace();
    }
    return null;
}

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

}

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

    }
 }