gpt4 book ai didi

java - 更改 ConcurrentHashMap 上的现有 foreach 循环以使用 Lambdas 来利用并行处理

转载 作者:搜寻专家 更新时间:2023-10-31 20:33:33 25 4
gpt4 key购买 nike

我正在制作一个游戏,并且有一个 ConcurrentHashMap,其中包含当前登录的所有玩家。我有一个 AutoSaver 线程,它循环遍历 HashMap 并逐一保存所有玩家。当玩家不多,这很好,因为它不需要太多时间来迭代,但是当有很多玩家登录时,它可能会变慢一点。我使用 java 流和并行读取,我们可以加快集合的处理,所以我尝试将现有循环更改为现在使用streamparallel

我的问题是,我的实现是否正确?有更好的方法吗?现在线程安全了吗?

这是现有的实现

for(Player player : ActiveConnections.getAllConnectedPlayers().values(){
if(player != null)
saveManager.savePlayer(player, true);
}

这是我使用流和并行的实现

ActiveConnections.getAllConnectedPlayers().values()
.stream()
.parallel()
.filter((x) -> x != null)
.forEach((x) -> saveManager.savePlayer(x, true));

编辑这是我的保存管理器实现

public class SaveManager {

private MySqlManager sqlManager;

public SaveManager(){
sqlManager = MySqlManager.getInstance();
}

public void savePlayer(Player player, boolean autoSave){
//Saves the player
}

同样,我刚刚开始使用 lambda,所以如果有什么问题请告诉我。

最佳答案

如果 savePlayer 是线程保存的,那么它是线程安全的。将流转换为并行流并不能使其成为线程安全的,而是使算法能够并行化。

但是,如果您的 savePlayer 将内容保存在数据库中,则无法并行化您想要的播放器保存部分。这意味着您看不到使用并行流有任何好处,因为当一个线程更改数据库的内容时,可能会发生两件事:

  • 第二个线程想要拯救另一个玩家,等待第一个线程完成。如果是这种情况,那么使用并行流就没有任何好处,因为线程仍然需要相互等待。

  • 第二个线程尝试在第一个线程同时更改数据库数据,这可能会导致数据库中的数据不一致。假设您的代码支持与数据库的多个 Activity 连接。

总之,当您要执行的算法是可并行化的时,您应该使用并行流。在内部,parallelStream() 将流分成子流,并在每个子流上(并发)执行每个项目的算法,最后使用相同的算法组合每个子流的结果。

“Java 8 in Action”一书中的示例:

public static long parallelSum(long n){
return Stream.iterate(1L, i -> i + 1) // generate a stream of long values, starting at 1
.limit(n) // limit the stream to n items
.parallel()
.reduce(0L, Long::sum); // this is what we want to execute concurrently, and in the end the result of each sub-stream will be combined using this sum
}

有关更多信息,请参阅本书的第 7 章。

关于java - 更改 ConcurrentHashMap 上的现有 foreach 循环以使用 Lambdas 来利用并行处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31099682/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com