Reputation: 6870
I am starting to think about multithreading for my game and the best place to start would be to seperate the three main components of the game: logic, gfx, sfx, into 3 seperate threads. The problem is they all need to access the same hashmap
of entities as the logic, gfx and sfx are completely seperate from eachother.
private Map<String, Entity> entities;
private Map<String, GameSound> sounds;
private Map<String, ArrayList<BufferedImage>> images;
The same hashmap is passed around to the different classes and object corruption is very likely with multiple threads. Currently the SoundsEngine
is the one threaded (else the music pauses between Thread.sleep()
and that is fine as it doesn't change, it just reads.
Is there an easy (and not hardhitting on performance) way to implement a threadsafe HashMap
without adding synchronized all over my code (and probably introducing more bugs this way)? I thought about taking a shallow copy every 60 frames as that is the maximum rate anything in my game will change and passing the copy around in the gameloop to the different engines but that seems a bity "hacky".
The concurrency problem is show by the constructors in the factory:
public class Factory {
private Map<String, Entity> entities;
private Map<String, GameSound> sounds;
private Map<String, ArrayList<BufferedImage>> images;
private GameEventListener listener;
private GameFrame frame;
private ImageLoader Iloader;
private SoundLoader Sloader;
public Factory() {
this.Iloader = new ImageLoader("imagelist.txt", images);
this.Sloader = new SoundLoader("soundlist.txt", sounds);
this.frame = new GameFrame(Color.black);
this.listener = new GameEventListener();
}
public GameEngine createGameEngine() {
return new GameEngine(entities, images, sounds);
}
public SoundEngine createSoundEngine() {
return new SoundEngine(entities, sounds);
}
public GraphicsEngine createGraphicsEngine() {
return new GraphicsEngine(entities, frame);
}
}
Edit: Singletons not an option, already did that in a previous game, I want to learn a more "loose" design in which I can independently develop the engines without breaking something because I have the wrong state.
Upvotes: 2
Views: 453
Reputation: 303
Using ConcurrentHashMap is better as it does not use synchronized block. It is so more efficient and faster. Collections.synchronizedMap is a proxy where a synchronized block will be added to each method call.
Upvotes: 1
Reputation: 13066
If you want to get synchronized version of your Hashmap then you can use the following inbuilt method of java.util.Collections
class:
Map m = Collections.synchronizedMap(new HashMap(...));
Apart from that java.util.concurrent.ConcurrentHashMap
is a better option for you.
Upvotes: 4