Sne*_*neh 5 java parallel-processing lambda
我正在制作一个游戏,并且有一个ConcurrentHashMap,其中包含当前登录的所有玩家.我有一个AutoSaver线程循环通过HashMap并将所有玩家1保存为1.当没有多少玩家时这很好,因为它迭代时间不会太长,但是当有很多玩家登录时它会慢一点.我使用java流和并行读取,我们可以加快集合的处理,所以我尝试将现有循环改为现在使用流和并行.
我的问题是,我的实施是否正确?有没有更好的方法呢?它现在是线程安全吗?
这是现有的实现
for(Player player : ActiveConnections.getAllConnectedPlayers().values(){
if(player != null)
saveManager.savePlayer(player, true);
}
Run Code Online (Sandbox Code Playgroud)
这是我使用流和并行的实现
ActiveConnections.getAllConnectedPlayers().values()
.stream()
.parallel()
.filter((x) -> x != null)
.forEach((x) -> saveManager.savePlayer(x, true));
Run Code Online (Sandbox Code Playgroud)
编辑 这是我的保存管理器实现
public class SaveManager {
private MySqlManager sqlManager;
public SaveManager(){
sqlManager = MySqlManager.getInstance();
}
public void savePlayer(Player player, boolean autoSave){
//Saves the player
}
Run Code Online (Sandbox Code Playgroud)
我刚刚开始使用lambdas,所以如果出现问题请告诉我.
如果 savePlayer 是线程保存的,那么它就是线程安全的。将流转换为并行流并不意味着它是线程安全的,而是使算法能够并行化。
但是,如果您的 savePlayer 在数据库中保存内容,则无法并行化您想要的玩家保存部分。这意味着使用并行流不会带来任何好处,因为当一个线程更改数据库的内容时,可能会发生两件事:
第二个线程想要拯救另一个玩家,等待第一个线程完成。如果是这种情况,那么使用并行流就没有任何好处,因为线程仍然必须相互等待。
第二个线程尝试在第一个线程的同时更改数据库数据,这可能会导致数据库上的数据不一致。假设您的代码支持多个到数据库的活动连接。
总之,当您要执行的算法可并行时,您应该使用并行流。在内部,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
}
Run Code Online (Sandbox Code Playgroud)
欲了解更多信息,请参阅本书第 7 章。