I'm using Properties in my code and I'm curious about multiple access.
I'm in the following case :
public Class MClass{
private static Properties dicoCategories = new Properties(myPropertyFile);
public void changeProperties(){
// changing properties and updating the file
}
}
MyClass is instanciated multiple times and each instance can modify the property file
. I guess I could manage this concurrency using temp files and locks, but I would prefer to use an already existing function. However, I found none. My question is : does the Property class manages concurrency a special way, or is there a multi-users equivalent ?
Although the Properties file is thread-safe, if you modify it using multiple invocations you still need to ensure thread safety. e.g.
properties.set(name, value);
is thread-safe, but
if (properties.get(name) == null) {
properties.set(name, value);
}
is not thread-safe without additional guards, and you should synchronise around such sequences.
It's not clear from your question whether your real issue is with multiple processes accessing this properties file, and if that is the case, then perhaps file locking is appropriate. See this question/answer for more info.
According to the documentation:
This class is thread-safe: multiple threads can share a single Properties object without the need for external synchronization.
According to the Java API, it is thread-safe:
http://docs.oracle.com/javase/6/docs/api/java/util/Properties.html
This would mean that you're OK making changes from different threads concurrently. However I would run a simple concurrency test to be 100% sure. You can also go into the source file and see how Java handles it internally...
As per Java documention
This class is thread-safe: multiple threads can share
a single Properties object without the need for external synchronization
So, answer is that you can use the Properties instance in multi-threaded environment.
What you need to keep in mind is that if the updates to Properties are very frequently done, then, it is possible that your application can become slow due to implicit synchronization within Properties. However, if it is once in a while, then you should be fine.
Related
So I was searching about storing data in one class, and found this. However, that's not what I'm looking for. What I wanted to know about this was whether it's bad practice, can cause performance issues in an application, or if there's another way to do it, etc... (and I'm not doing this on an Android).
Let's say I have a class that stores a HashMap<Enum, Object> and is initialized when I create the class in main.
public Main() {
// Creates the HashMap, initialized in the constructor 'MemoryContainer'
MemoryContainer m = new MemoryContainer();
m.getTestHash().put(SomeEnum.TEST, "Test"); // Using created HashMap
}
Other than casting the value every time I use it, would this cause major issues? If so, is there an alternative?
There's nothing wrong with storing static values in a class, however this is not a good practice.
To store the constants you should create an interface as every field in an interface is already a constant (public static final).
A better approach will be to store these values in properties files, and load them as needed.
A properties file can be stored externally and a person who isn't aware of your source code would be able to modify this properties file if needed. For example you can store database connection details in properties files and if server support admin determines that database instance is down, he/she can edit the properties file to point the application to a new one.
Finally for most flexibility you shouldn't store the configuration inside application at all. It can be stored in a database like MySql or in a fast data structure storage like Redis. This will allow multiple instances of your application to share the configuration data and it will also allow you to modify configuration on the fly by modifying them in the database.
Sometimes a Git repository is also used to store this kind of data (like in case of microservices). Git repository in addition to being shared among all the instances, also maintains the history of modifications.
I would not look too much at performance issues (of course, I do not know what else your application does or wants to do and how it achieves it).
What you should look at first is Mutability - in your example, nothing would stop me from changing the configuration at Runtime by calling
m.getTestHash().put(SomeEnum.TEST, "NotATestAnymore") - this would immediately change the behaviour for every other use of that specific setting.
I am also not sure why you would not just use a configuration class that would directly provide (typed) getters and, if you know all configuration settings at the launch of the app, one constructor containing all the settings.
Do you plan to read the configuration from an outside source (e.g. file)?
NO,
It won't cause major issues.
Also, it is a good practice to keep those variables (HashMap in your case) in a different class away from your main class (which contains your app logic).
how
lets say i have this class
#ImmutableWannabe
public class ConfigurationHolder {
#ImmutableButHowToMakeSureNoTwoThreadsOverrideOneEachOtherWhenReplacingReference
private Map<System, Configuration> mySysConfig = ImmutableMap.builder<>getSomeConfigurations....build();
ConfigurationHolder(copy constructor) {
mySysConfig = ImmutableMap.builder().of(inputSysConfig);
}
}
Now lets say one of the systems configuration has updated and i need to update this map of however I need to do it in a thread safe way. which means if two threads try to update the same configuration of same system data should be consistent and they should not override one each other.
How did immutability help me here? As far as i can see i still need to do locking if yes how to do it properly?
so my general question is: isn't it the case that any immutableObject which can change over system time will cause us to need to lock the code that will need to change its ImmutableObjectHolder? I don't get it...
can someone please give a proper example of an ImmutableMap + Holder for that Map + proper "client" code that knows to update this ImmutableMapHolder with updates to the internal Map?
thanks
Assuming your map is some instance variable, the simplest way it to make it volatile. Alternatively, make a getter and setter for it and make them synchronized. i.e., use standard techniques. And note that this won't help if the client tries to be clever and cache the value in a local variable. (I've bitten myself with this bug a couple of times.)
I guess as an alternative you could setup some MyImmutableChanged event/listener.
And, you are correct, immutability doesn't solve every threading problem.
I am working on a existing web based application which uses static map to store data specific to the Application .
This is my code below which is responsible to store Data inside a ConcurrentHashMap as shown below .
public class MyClass
// Class variable
private static Map<String, UserThread> usermap = new ConcurrentHashMap<String, UserThread>();
// Inside a Method
public void userData()
{
UserThread userThread= usermap.get(getLoginId());
if (userThread == null) {
userThread = new UserThread();
userThread.start();
usermap.put(getLoginId(), userThread);
}
}
The application is working fine , here my question is that , is this a valid code because can we store Data inside a static variable ?? (Here the Static ConcurrentHashMap contains data specific to the Application )
Static variables and caches of any kind should be avoided, especially in multi-threaded environments such as web-applications. There are several problems with your code:
Do you remove UserThreads from the map? How do you know when they should be removed? What if client's browser crashes? If you don't remove them you are asking for out-of-memory errors after the application is running for some time.
Using ConcurrentHashMap in the way you use it is not thread-safe, because it's possible that another thread adds a UserThread between if (userThread == null) and usermap.put(getLoginId(), userThread); . Concurent version of HashMap doesn't magically solve all problems with thread-safety as it may seem.
Spawning your own threads in a servlet container is not a good idea. There are better ways to do background tasks, but first you need to say what the thread is trying to do.
Generally using any kind of such static caches is bad idea, in any kind of application. In your case it would be much better to keep application-specific data in user's session.
With static map, you would run into the risk of memory leak unless you are sure of the life cycle of each entry added to the map, i.e. who would be adding them, how long will the entries stay there and when will they be removed so that they can be claimed during GC. Otherwise, your application will use up the memory and will start throwing OOME.
In this case, user which will log in on one machine will have the same session as on the second machine. I bet it's not a good way to do.
I had asked some time ago about Semi static field in Java application and Alessandro Santini gave me very nice solution with ThreadLocal. Check this out.
AFAIK it is according to the specification not ok to start your own thread inside a container. You are supposed to use a WorkManager for this. But the only server I know of that actually is enforcing that rule is Websphere Application server.
a static variable in principle is ok, of course if you run in an clustered environment each server will have its own instance of the static variable. This might or might not be a problem.
So technically you might be fine.
On the other hand I am really curious what you are trying to achieve with all these threads. If you start one thread per user this is an excellent attack vector for DOS attacks. I also have no idea why you would want to do something like this.
In the database, I have a definition table that is read from the application once upon starting. This definition table rarely changes, so it makes sense to read it once and restart the application every time it changes.
However, after the table is read (put into a ResultSet), it will be read by multiple handlers running in their own threads.
How do you suggest to accomplish this?
My idea was to populate a CachedRowSet, and then create a copy of this set (through the createCopy() method) for each handler every time a new request comes.
Do you think this is wise? Does this offer a good performance?
Thanks.
It may be better for you to use the singleton pattern. This would allow you to create a single class that all of your threads could access to get the object that they needed. This could also allow you to not have to shut down your application whenever changes are made. One way to accomplish this is to have a class where you have get and set methods for the information you need. And another class that will give out references of that object.
The class that gives out references could have a private constructor, and a getInstance method that will return a reference to itself to ensure that only one exists. This would also give you some other options regarding what you can do when things change.
Ok, if you control access to the resultSet, and you don't care to update the result set until you restart the application, then i would suggest wrapping the CachedRowSet in a custom class. One possible way to do this is to have a wrapper class that is a singleTon and provide it with getter methods so that other threads or classes for that matter can access it. That way you remove the need to make a copy and remove the dependency on CachedRowSet implementation. Creating a copy would cause unnessary overhead. Imagine, in the way you described above, if you had 1000 threads accessing your result set, you would call createCopy() 1000 times thus creating a 1000 copies of the same resultSet.
I think it is a pattern to read the configuration table into a static data structure (ConcurrentHashMap) and then let the threads to look it up.
You can ensure that there is no write race at startup by populating the reference map from a Servlet.init() - it is guaranteed to execute once per servlet.
I have a static object defined in my logging class, along the lines of:
class myLoggingClass {
static java.util.Properties properties;
...
...
}
According to my reference book, this means that the properties object is shared by all instances of my class.
I find this definition insufficient. I'm writing a class that is being invoked more than once in each application on our project.
Further, our project uses several web services running in the same tomcat container. Each web service may have multiple threads.
The Java Virtual Machine running on the host may also run one or more web service client applications, which run external to tomcat.
So by this definition, I may have tomcat running multiple web services with threads, each having several objects, which may contain an instance of my class.
There may also be one or two web clients running outside of tomcat, but within the same JVM. Would all of these instances of my class share the same properties object? That would make it JVM-wide.
If the static object is not JVM-wide, does anyone know at what level each one would exist? One per tomcat container? One per web service, and one per standalone web service client application?
The reason: When I update my properties, I'm getting a java.lang.ConcurrentUpdateException from java.util.Properties.
I'm using a static boolean variable to "lock" the properties object when my class updates it, but this is not keeping the exception from occurring.
This leads me to believe that the static object used in my class may not be at the same scoping level as the one used in java.util.Properties... But that's just a guess.
Thanks for any help.
Statics aren't "shared by all instances of a class" - they're unrelated to instances; they belong to the type itself. In particular, static variables are perfectly usable without any instances being created.
That gives a clue as to the scope of statics: they're scoped by the Class object representing the containing class, which is in turn scoped by the ClassLoader that loaded it.
Depending on where the library is placed, the static variable may be JVM-wide or web-application wide - or possibly something in between, if Tomcat supports multiple hosting (I can't remember offhand).
Look at the Tomcat documentation for how the libraries are laid out and how they relate to class loaders. For example, here's the Tomcat 6.0 ClassLoader how-to guide, and the equivalent for 5.5.
How does your Boolean "lock" work? You should really use a proper lock (synchronized) to make sure that every use of the properties object (both read and write, including locking for the whole period during which you iterate through it) is appropriately locked.
Instead of changing the "live" Properties object, have you considered treating that as immutable - so when you want to update the properties, you take a copy, change that, and then make the copy the "live" version? You'd still need to prevent two different threads from making changes at the same time (or you'd lose some) but it's likely to make the reading side a lot easier and more efficient.
You may find that the scope of such a static variable is limited to one per ClassLoader that has loaded your class. I'm not sure how Tomcat arranges its ClassLoaders, so it's hard to say what the extent of the scope will be in that environment.
The likely cause of your ConcurrentModificationException is that you are iterating thru the values/entries of the Properties object in one thread while another modifies it at the same time. You cannot do this.
Can you elaborate on the locking mechanism that you mention here:
I'm using a static boolean variable to "lock" the properties object when my class updates it, but this is not keeping the exception from occurring.
?
Because it doesn't sound as if you are using the built-in locking and synchronization methods in Java.
Something like this should prevent threads from reading the Properties object while another thread updates it:
static Object lockObject = new Object();
...
synchronized(lockObject) {
// access the Properties object
}
Note that you will need to do this every time you access the Properties object, either to read it or modify it.
Also I would never recommend static objects to share data among all instances or static lockObjects - global data is evil - but it sounds as if you need this for some reason.
Could it be a classloader problem where the jar that contains your class is duplicated in each WEB-INF/lib of your different applications?
If so, I would try to add this jar to Tomcat libs and not to the application.