I'm working on a program which needs to load the same information from option files in multiple threads. Therefore I made a simple class representation of each file based on an abstract model: (shown below is 1 example of many of these classes)
package OptionManager;
import java.util.Properties;
public class EngineOptions extends AbstractOptions{
//values
private static String debugEnabled;
private static String debugAvgLoadtime;
private static String showShaderUsed;
private static String mainLanguage;
//keys
public static final String DEBUGENABLED_KEY = "debugEnabled";
public static final String DEBUGAVGLOADTIME_KEY = "debugAvgLoadtime";
public static final String SHOWSHADERUSED_KEY = "showShaderUsed";
public static final String MAINLANGUAGE_KEY = "mainLanguage";
public static String getProperty(String key) {
return properties.getProperty(key);
}
public static void loadFromFile(String filename) {
OptionReader loader = new OptionReader(filename);
//load properties
debugEnabled = loader.getProperty(DEBUGENABLED_KEY);
debugAvgLoadtime = loader.getProperty(DEBUGAVGLOADTIME_KEY);
showShaderUsed = loader.getProperty(SHOWSHADERUSED_KEY);
mainLanguage = loader.getProperty(MAINLANGUAGE_KEY);
properties.put(DEBUGENABLED_KEY, debugEnabled);
properties.put(DEBUGAVGLOADTIME_KEY, debugAvgLoadtime);
properties.put(SHOWSHADERUSED_KEY, showShaderUsed);
properties.put(MAINLANGUAGE_KEY, mainLanguage);
}
}
Here is the abstract class it uses:
package OptionManager;
import java.util.Properties;
public abstract class AbstractOptions {
protected static volatile Properties properties;
public static void setupProperties() {
properties = new Properties();
}
public static void setupProperties(Properties properties) {}
public static void setProperty(String key, String value) {
if(properties.getProperty(key) == null) {
//throw exception.
}
properties.setProperty(key, value);
}
public static String getProperty(String key) {
System.out.println(properties);
return properties.getProperty(key);
}
//public static void loadFromFile(String filename) {}
}
I'm able to load the option files in the main thread(the one created by the JVM in order to start the program) and use this system within this thread to get all the options I want. Infact as a test I print the entire list of options in the EngineOptions class every time I access an option giving the following output(when getting the mainLanguage option):
{mainLanguage=language_IT, debugAvgLoadtime=1, debugEnabled=1, showShaderUsed=1} language_IT
However when I try to access the same option inside another thread(created by the main thread and started after I print the output above) I get this:
{} null
This leads me to believe that for each thread the values of my static fields aren't shared. So I found this answer which suggested using 'volatile' to solve the problem. However this didn't work.
Another option is to load option files in every thread but I would like to not do that as the reason I had to load option files multiple times for each thread was the reason I created this system in the first place.
How can I fix this problem and share the values of the option over multiple threads?
EDIT:
How I create a new option list:
OptionHandler.addOptionFile(OptionHandler.ENGINE_OPTION_ID, new EngineOptions(), "EngineOptions");
OptionHandler.loadOptionListFromFile(OptionHandler.ENGINE_OPTION_ID, OptionHandler.ENGINE_OPTION_TYPE);
How I call the option from the thread:
String currentLang = OptionHandler.getProperty(EngineOptions.MAINLANGUAGE_KEY, OptionHandler.ENGINE_OPTION_ID);
System.out.println(currentLang);
EDIT 2:
package OptionManager;
import java.util.HashMap;
import java.util.Map;
public class OptionHandler {
private static HashMap<Integer, AbstractOptions> optionList;
private static HashMap<Integer, String> optionFilename;
//OptionFIleID's (Starting from 101 to 199)
public static final int GRAPHIC_OPTION_ID = 101;
public static final int ENGINE_OPTION_ID = 102;
public static final int CURRENT_LANGUAGE_ID = 103;
public static final int GRAPHIC_OPTION_TYPE = 201;
public static final int ENGINE_OPTION_TYPE = 202;
public static final int CURRENT_LANGUAGE_TYPE = 203;
public static void setupOptions() {
optionList = new HashMap<Integer, AbstractOptions>();
optionFilename = new HashMap<Integer, String>();
}
public static void addOptionFile(int id, AbstractOptions options, String filename) {
options.setupProperties();
optionList.put(id, options);
optionFilename.put(id, filename);
}
public static String getProperty(String optionKey, int optionFileID) {
return optionList.get(optionFileID).getProperty(optionKey);
}
public static void loadOptionListFromFile(int id, int type) {
System.out.println(optionFilename.get(id));
if(type == GRAPHIC_OPTION_TYPE)
GraphicOptions.loadFromFile(optionFilename.get(id));
if(type == ENGINE_OPTION_TYPE)
EngineOptions.loadFromFile(optionFilename.get(id));
if(type == CURRENT_LANGUAGE_TYPE)
CurrentLanguage.loadFromFile(optionFilename.get(id));
}
}