简体   繁体   中英

How to load properties from config.properties in multithreaded environment in JAVA


I have program that loads in main class properties from file config.properties like this :

    public class DirectoryWatcher {
       public static String FOLDER = null;
       Properties prop = new Properties();

       prop.load(new FileInputStream(new File(configPath)));
       FOLDER = prop.getProperty("FOLDER");
    }        

Many threads needs FOLDER, because of it I set it to be public static , so threads can use it.

I am not like this kind of programming and I am looking for some best practice implementation.
Can you suggest me something better? Thank you.

For me this would be simply enough

public class DirecoryWatcher{
    private static String FOLDER;

    public static synchronized getFolder(){
        if(FOLDER == null){
            // FOLDER = your loading code
        }
        return FOLDER;
    }
}

Make sure to assign the value you read from the file to your static field, so you make sure you read it only once.

Also, synchronized methods is a good practice for accessing resources, it's not completely mandatory for this case, since you're only reading the file.

You can also make this approach extensible to read any property given as argument. I hardcoded FOLDER for the sake of clarity.

public class DirectoryWatcher{

   private static Map<String,String> properties = new HashMap<String,String>();

   public static synchronized getValueFor(String prop){
       String result = null;
       if( !properties.keySet().contains(prop)){
          result = // your loading code
          properties.put(prop, result);
       }else{
          result = properties.get(prop);
       }
       return result;
    }
}

This code will give you thread-safety and support for any given number of properties. It also enhance the encapsulation of your code, you can add some logic to it (you're not just exposing the content of your file).

Besides, following this case, properties are not loaded until they are first required. If a property is never used, then it won't be read. That improves your memory usage, you don't waste memory on values you won't need.

Another important thing to consider is that, with this implementation, your properties loader class can handle errors and exceptions very easily. With the other approach, you delegate the responsibility of handling problems to the object that requested the property.

You can make it final:

private static final Properties prop = new Properties();
public static final String FOLDER;

static {
    try {
        prop.load(new FileInputStream(new File(configPath)));
    } catch (IOException ex) {
        //outch => log and exit?
    }
    FOLDER = prop.getProperty("FOLDER");
}

This will ensure that it is visible from any threads. If you have more than a handful of properties, you can also use this example which uses an enum and is thread safe.

Maybe you can use Singleton pattern for this problem?

Also you use lazy loading for folder if you have big number of information for loading.

you can define a simple property file reader like this

public class LoadDataFromPropertiesFile {

public final static Properties loadPropertiesFile(String fileName) {
    ClassLoader loader = Thread.currentThread().getContextClassLoader();
    InputStream inStream=null;

    try {
        inStream =  loader.getResourceAsStream(fileName);
        if (inStream == null) {
            throw new RuntimeException("Couldn't find " + fileName + "in class path");
        }
        Properties prop = new Properties();
        prop.load(inStream);

        return prop;
    } catch (IOException e) {
        e.printStackTrace();
        throw new RuntimeException(e);
    }finally {
        if (inStream != null) {
            try {
                inStream.close();
            } catch (IOException e) {
                e.printStackTrace();
                throw new RuntimeException(e);
            }
        }
    }       
}   
}

specific property files can be read like below.

public class DirectoryWatcher {
public static final Properties directoryWatcher;
static {
    directoryWatcher =     LoadDataFromPropertiesFile.loadPropertiesFile("config.properties");
}     

}

Properties you can define as ENUM type ... you can list your properties here

public enum DirectoryProperties {
        FOLDER("FOLDER","Directory Type Folder"),
        IMAGE("IMG","Image File");
;

DirectoryProperties(String code, String description) {
    this.code = code;
    this.description = description;

}

public String getCode() {
    return code;
}

public String getDescription() {
    return description;
}

private String code;
private String description;

}

You can use your properties in any thread. like this

DirectoryWatcher.directoryWatcher.getProperty(DirectoryProperties.FOLDER.getCode());

you can use description where required.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM