Reputation: 3297
Consider a java process, in that the main thread reads Json objects from a source and assigns a task with the read Json objects to a FixedThreadPoolExecutor with 5 worker threads.
Here the problem is, the source from which the Jsons are read is much faster than the completion of the tasks by the worker thread. So, as the Jsons accumulate in memory waiting for the worker threads, OutOfMemoryException is thrown. Here the number of worker threads cannot be increased.
So will the following be an efficient solution to this OutOfMemory problem?
In main thread check the percent of available memory and sleep for some time if the memory usage is more than 80%
main(){
for(;;){
//read the data and assign to executor
long total = Runtime.getRuntime().maxMemory(),free = Runtime.getRuntime().freeMemory()
float usedPersent = (total-free)*100/total
if(usedPercent > 80)
Thread.sleep(2000);
}
}
Will there a good practice?
Upvotes: 0
Views: 124
Reputation: 200168
You should solve your OOME problem with proper design instead of hacks. Your JSON objects should be pushed into a bounded blocking queue, which will automatically take care of applying "backpressure" against the producer.
An even cleaner option would be to redesign so that each of your submitted tasks is given a portion of the loaded JSON to process, so it does not pull anything on its own. This way you don't even need to implement the queue: you rely on the queue internal to your Executor Service, which you only need to configure appropriately. For example, use an explicit ThreadPoolExecutor
constructor, passing it the CallerRunsPolicy
as Rejection Policy.
Also note that loading too much JSON in advance will slow down your system overall because the excess objects will be promoted to the Old Generation, increasing the frequency of Major Garbage Collections.
Upvotes: 4
Reputation: 9872
I am not sure about that idea. Where does you main thread retrieve its work from? Is it keeping clients slept and waiting as well during those 2 seconds?
I think you have 2 ways to attack this problem:
http://www.jafaloo.com/java-xmx-memory-settings/
If you provide them with a sound estimation of the amount of memory you need, they should be reasonable (yes, I have treated with tough operators in my life :P)
Upvotes: 0
Reputation: 5185
No it's a bad idea. As far as I know the behaviour of a JVM is simply not specified after an OutOfMEmoryException occured (sorry, I don't have the links right now). You might not even see this exception in some cases. So it is essential to monitor JVM heap usage, e.g. in server environments.
Upvotes: 1
Reputation: 86524
A better solution would probably be a queue that blocks when it's full. That way, you keep the backlog manageable without the funkiness that is thread synchronization via Thread.sleep
.
Upvotes: 0
Reputation: 65821
No - this is a bad idea.
You should create your thread pool with a maximum pool size and a limited length queue size and handle rejections properly.
There's a post here that looks promising. It professes to be a BoundedExecutor
.
Upvotes: 1