I am making a game and have a ConcurrentHashMap which contains all the players which are currently logged in. I have a AutoSaver thread which loops through the HashMap and saves all the player 1 by 1. When there are not many players this is fine as it doesn't take too much time to iterate but it can slow down a bit when there are many players logged in. I read using java stream and parallel, we can speed up processing of collections, so I tried changing my existing loop to now use stream and parallel.
My question is, is my implementation correct? Is there a better way to do it? Is it thread safe now?
Here is the existing implementation
for(Player player : ActiveConnections.getAllConnectedPlayers().values(){
if(player != null)
saveManager.savePlayer(player, true);
}
Here is my implementation using stream and parallel
ActiveConnections.getAllConnectedPlayers().values()
.stream()
.parallel()
.filter((x) -> x != null)
.forEach((x) -> saveManager.savePlayer(x, true));
EDIT Here is my save manager implementation
public class SaveManager {
private MySqlManager sqlManager;
public SaveManager(){
sqlManager = MySqlManager.getInstance();
}
public void savePlayer(Player player, boolean autoSave){
//Saves the player
}
Again I have just started using lambdas so please let me know if there is something wrong.
It is thread safe if savePlayer is thread save. turning a stream into a parallel one doesn't make it thread safe, it makes the algorithm able to be parallelized.
However, if your savePlayer save stuff in the data base, then there is no way to parallelize the player saving part which is what you would like. Meaning that you'll see no benefit from using a parallel stream because when one thread changes the contents of the DB, two things can happen:
the second thread that wants to save another player, waits for the first thread to finish. If this is the case, then there is no benefit of using parallel streams because threads still have to wait for each other.
the second thread attempts to change DB data at the same time has the first thread which may lead to incoherent data on your Database. Assuming your code supports more than one active connection to the database.
In sum, you should use parallel stream when the algorithm you want to execute is parallelizable. Internally, parallelStream() divides the stream into sub-streams, and executes the algorithm for each item on each of the sub-streams (concurrently), in the end the result of each sub-stream is combined using the same algorithm.
An example from the "Java 8 in Action" book:
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
}
For more information refer to chapter 7 of the book.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With