I have a singleton class in my play app. This singleton class is a long process which will generate reports from DB which consumes huge amount of memory. When i run my application in dev mode this singleton functionality is executing several times. I want this functionality to run only once. What should I do for that?
My code is:
public class DataGridManagerImpl extends ComponentContainer implements DataGridManager {
private static DataGridManager instance = null;
private DataGridManagerImpl(){
load();
}}
#Override
public void load() {
//Myreports function
}
public static DataGridManager getInstance(){
if (instance == null){
instance = new DataGridServiceManagerImpl();
}
return instance;
}
}
In my controller file inside a template function
DataGridManager dataGridMgr = DataGridManagerImpl.getInstance();
If i access the page it is executing the load reports function again.
Without code explaining how did you create your class it's hard to answer. From what I understand what you want is to run a process only once.
Problably the best approach is to use a Scheduled Job. This will trigger the process at a certain time, and Play ensures that only 1 instance of this process is running at the same time, even if the schedule would indicate another instance has to run. Let's say you have a process scheduled every hour and the process takes 3 hours. The initial process will be the only one running for 3 hours until it finishes.
Now, I would assume you want your process to be recurring as it generate reports. If not, if you only want to run it once, then you may want to use an asynchronous bootstrap job instead. This would run just once, at the beginning of the application.
EDIT on update: during development the #OnApplicationStart may execute several times, as Play may automatically reload the application when you do certain code changes. This is part of the dev process (the same that an #OnApplicationStart job won't start in Dev until the server gets a request).
As it's a job that you only want to run once, you may try to skip it in dev mode using the check:
if(Play.mode == Play.Mode.DEV)
If you need to run it at least once, add a dev-only url that you can access during dev to start the process.
Now, on your update you also mention that you are calling that code in a controller, and that every time the controller is acessed the method is called. That's expected. Singleton doesn't mean that it will run only once, but that there is only 1 object in the system. If in your controller you launch the calculation, that will happen everytime you access the controller.
SECOND EDIT (on comments): Arasu, the other issue is that you are calling the method load() when you construct the object. A singleton doesn't garantee that the object will only be constructed once. It garantees that, once constructed, only 1 object will exist. But it may happen that the object is removed by GC, in this case as per your code if you construct it again then you'll call load() and redo the processing.
The best solution is to not call "load" on constructor, but to force the user (you) to call it after retrieving the instance. An alternative is to set some flag at the beginning of load that detects if the code has been run. Be aware that Play is stateless, so that flag will need to be stored in the database.
the defition of a singleton is that it can run only once, it's practically the nature of the pattern. If you somehow manage to run it multiple times, you might have implementation errors in your singleton.
Recheck the singleton pattern in Wikipedia.
Edit:
This code makes it impossible to fetch more than one instance. How would you get more than one?
public class Singleton {
private static Singleton _instance;
private Singleton() { }
public static synchronized Singleton getInstance() {
if (null == _instance) {
_instance = new Singleton();
}
return _instance;
}
}
Or do you mean that you instanciate the Singleton class, instead of calling Singleton.getInstance()?
It is possible to have a Singleton doing a time consuming processing and be called the same time by two different threads. I think this is the situation here. The same Singleton object's method is called multiple times from the program.
I have run a little test... two thread calling the same Singleton object and here is the result
Thread[Thread 1,5,main] internal loop number = 0 Object = example.Singeton#164f1d0d
Thread[Thread 2,5,main] internal loop number = 0 Object = example.Singeton#164f1d0d
Thread[Thread 1,5,main] internal loop number = 1 Object = example.Singeton#164f1d0d
and here is the code.
package example;
public class Singeton {
private static final Singeton INSTANCE = new Singeton();
private Singeton() {}
public static Singeton getInstance(){
return INSTANCE;
}
public boolean doTimeConsumingThing(){
for (int i=0; i<10000000;i++){
System.out.println(Thread.currentThread() + " internal loop number = " + i + " Object = " + toString());
}
return true;
}
}
package example;
public class MulThread extends Thread{
public MulThread(String name) {
super(name);
}
#Override
public void run() {
while(true){
Singeton s = Singeton.getInstance();
System.out.println("Thread " + getId());
s.doTimeConsumingThing();
}
}
public static void main(String[] args) {
MulThread m1 = new MulThread("Thread 1");
MulThread m2 = new MulThread("Thread 2");
m1.start();
m2.start();
}
}
Please correct my notion above if i am wrong.
Hence what you need is a variable to keep track of the state of the time consuming procedure (i.e. a boolean isRunning) or the times the procedure has been called.
You can also make the pertinent time consuming method of the Singleton synchronized so only one thread can access the method while it is running (in my example if you make the doTimeConsumingThing() synchronized, the second thread will block until the singleton's method called from the first thread is finished.
Hope it helps
I had the same problem in DEV mode, and what I did is create a module for the tasks I don't want to be run at every #OnApplicationStart.
The trick is to launch those tasks in a overriden "onLoad()" method, in the module:
public void onLoad()
{
// tasks to run one time only
}
The onLoad() method is called one time only, not each time the application is restarted.
I don't know if this will help, but here are some things to check:
The code in your question is not thread-safe. You're missing the synchronized keyword in getInstance. That could cause the constructor to be called more than once by different threads.
Could DataGridManagerImpl be getting loaded by different classloaders? That static instance variable isn't static for the whole JVM, just static for that class' classloader.
load is public. Could some other code being calling that method?
Related
How multithreading behaves in case of static members? Like in case of Singleton Class, if I try to create instance in a static block and in the static method, I return the instance and two threads try to execute getInstance() at the same time..how will this behave internally as static are loaded only one time
public class SingleTonUsingStaticInitialization {
private static SingleTonUsingStaticInitialization INSTANCE = null;
static {
try {
INSTANCE = new SingleTonUsingStaticInitialization();
} catch (Exception e) {
e.printStackTrace();
}
}
private SingleTonUsingStaticInitialization() {
}
public static SingleTonUsingStaticInitialization getInstance() {
return INSTANCE;
}
}
This specific example?
Threadingwise it's fine. Style wise it's deplorable. Do NOT write catch blocks like that. It also means if an exception does occur (it can't here - your constructor is empty), your code will dump half of the info to system error, and then continue, with a null reference instance of an instance of Singleton - causing other code to spit out NullPointerExceptions (because code just keeps going, as you caught the exception instead of letting it happen). If you treat all exceptions in this fashion, a single error will cause hundreds of errors in your logs, all irrelevant except the first one.
Once you take care of this exception handling issue, you can make the variable final, and no longer assign null to it. While you're at it, make the whole class final. It effectively is already (as you only have a private constructor):
public final class Singleton {
private static final Singleton INSTANCE = new Singleton();
private Single() {}
public static Singleton getInstance() {
return INSTANCE;
}
The reason this works out when 2 threads simultaneously invoke getInstance, is the classloader mechanism itself: The Classloader guarantees that any given class is never loaded more than once by the same loader, even if 2 threads would simultaneously require this (the classloader will synchronize/lock to avoid this situation), and the initialization process (the static block - which was needlessly convoluted, as the example above shows) is similarly guarded and cannot possibly occur twice.
That's the only freebie you get: For static methods as a general rule, all threads can just run the same method all simultaneously if they want to. And here they do - it's just that the initialization (which includes the ... = new Singleton(); part) is gated to occur only once.
NB: If you must do more complex things, make helper methods:
public final class Singleton {
private static Singleton INSTANCE = create();
private Singleton(Data d) {
// do stuff with 'd'
}
private static Singleton create() {
Data d;
try {
d = readStuffFromDataIncludedInMyJar();
} catch (IOException e) {
throw new Error("states.txt is corrupted", e);
}
return new Singleton(d);
}
}
This:
Keeps code simple - static initializers are a thing, but fairly exotic java.
Makes your code easier to test.
It's an internal file; if that is missing/broken, that's about as likely / as problematic as one of your class files having gone for a walk. An Error is warranted here. This cannot possibly occur unless you wrote a bug or messed up a build, and hard crashing with a clear exception telling you precisely what's wrong is exactly what you want to happen in that case, not for code to blindly continue in a state where half of your app is overwritten with gobbledygook due to a disk drive crash or what not. Best to just conclude everything's borked, say so, and stop running.
You are safe, in the sense that getInstance will return the same instance to multiple threads. This is guaranteed by The JLS, which is the only place you should delegate your understanding to. Specifically, that chapter says:
For each class or interface C, there is a unique initialization lock LC
And goes on further to say that:
The procedure for initializing C is then as follows:
Synchronize on the initialization lock, LC, for C. This involves waiting until the current thread can acquire LC
In plain english, only a single thread can initialize that static field. Period.
The release of that lock gives proper happens-before guarantees between the action in the static block and any thread that uses that static field. This is implied from the same chapter, from:
An implementation may optimize this procedure by eliding the lock acquisition in step 1 (and release in step 4/5) when it can determine that the initialization of the class has already completed, provided that, in terms of the memory model, all happens-before orderings that would exist if the lock were acquired, still exist when the optimization is performed
Or, again, in plain english, whatever happens in that static block will be visible to all reading threads.
To that end, you will have a proper tool to remove that static block, via a so called "constant dynamic". The infrastructure for it is already in place, but javac still does not use it. You can read more here about it. Some projects already use that - if you have the proper jdk, for example jacoco does it.
See the fine points made in the Answer by rzwitserloot.
Here is similar code to the code seen there, but adapted to use an enum as your singleton. Many folks recommended an enum as the ideal way to define a singleton in Java.
Thread-safety is guaranteed because of the same class loader behavior discussed in the other Answer. The enum is loaded once, and only once, per class loader when the class first loads.
If you have multiple threads accessing the single object defined by this enum, the first thread to reach the point where this class is loaded will cause our enum object to be instantiated with its constructor method running. The other remaining threads will block on their attempt to access the enum object until the enum class finishes loading and its one and only named enum object finishes its construction. The JVM juggles all this contention automatically, with no further coding needed by us. All that behavior is guaranteed by the Java specifications.
package org.vaadin.example;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
public enum AppContext
{
INSTANCE;
private String wording;
AppContext ( )
{
try
{
readStuffFromDataIncludedInMyJar();
}
catch ( IOException e )
{
throw new Error( "Failed to load from text file. Message # 7a608ddf-8c5f-4f77-a9c9-5ab852fde5b1." , e );
}
}
private void readStuffFromDataIncludedInMyJar ( ) throws IOException
{
Path path = Paths.get( "/Users/basilbourque/example.txt" );
String read = Files.readAllLines( path ).get( 0 );
this.wording = read;
System.out.println( "read = " + read );
}
public static void main ( String[] args )
{
System.out.println( AppContext.INSTANCE.toString() );
}
}
When run.
read = Wazzup?
INSTANCE
I am new to Spring Boot and just implemented a normal Spring Boot application with HTTP where endpoints receive data and put in a database. Now I want some data to put in both databases and a class with data structure. Since there will be continuous operations with this data I need to operate with it as a separate process.
#Service
public class RulesManager {
private HashMap<Integer, Rule> rules = new HashMap<Integer, Rule>();
public void addRule(Rule rule) {
// Add rule to the database
}
// should be running in the background
public void updateRules(){
// Continuous check of rules and update of this.rules HashMap
}
}
#SpringBootApplication
public class RulesApplication {
public static void main(String... args) {
SpringApplication.run(RulesApplication.class, args);
// How do I call RulesManager.updateRules() to run in the background and make changes to rules hashmap???
}
}
So while listening to HTTP requests I want my application to run background process which will never stop and repeat itself. I am not sure how to call that class from the main RulesApplication class so that both http requests and background process were able to make changes to this.rules HashMap. Will be grateful for any tip or advice.
If you are just looking to start a always on process when app starts ( even better when RuleManager gets initialized ), then you should simply create a new thread in the constructor of RuleManager :
methodCalledByConstructor()
{
new Thread(()->{
// loop start
// access and check the hashmap
// do what is necessary
// sleep for a sometime
// loop end
}).start();
}
But if the work is only required when some event occurs, then use observer pattern for more elegant solution.
Try to define a new Thread for example "LocalRulesHandling" and annotate it with #Component and inside this thread add your implementations regarding the rules hashmap.
In the RulesApplication class try to get the spring context and the get the execution thread bean and then start this thread.
ApplicationContext conttext = SpringApplication.run(RulesApplication.class, args);
LocalRulesHandling handling = context.getBean(LocalRulesHandling.class);
handling.start();
i have a simple Jsp page that hits to servlet and in the servlet i call a method from another class and in this method i am declaring a static variable globally and setting a value to it and then the servlet's task is over so the control is back to the jsp page (or to a page that i forward the request and response to).
so wat just happened is termed a session???
the value set to that static variable remains the same for all the sessions that are coming next!! why is this happening. dint the earlier session end ?? if it has ended, then why is the value for the static variable that i have set is still remaining like that only in my subsequent sessions?? please correct me if i am wrong. Help me to learn! stackoverflow has never let me down!!!! thanks in advance
static fields in a class will live until the class itself is unloaded and garbage collected. So, static fields in a serlvet will not only live across all the sessions but across the whole application, in this case, until the web application is undeployed.
In fact, it is not wise to have any field in a servlet unless this field cannot be modified after being initialized or if it is injected by the container like an EJB or a CDI bean. This is because a single Servlet instance will be used to attend several requests made to the server, so even if you have a non-static field in your servlet and you update it through requests, its value can be modified by two or several requests happening at the same time. Try to keep the variables to the shortest possible scope, for example, inside a method only.
More info:
How do servlets work? Instantiation, sessions, shared variables and multithreading
From comments, looks like your real problem is about a design to support synchronization across several threads. A better option would be creating an object instance that will be shared among your threads, then use a final non-static field to handle the synchronization:
class MyClass {
final Object lock = new Object();
//other fields in the class...
}
class Multijobs {
class Job implements Runnable {
MyClass myClass;
public Job(MyClass myClass) {
this.myClass = myClass;
}
#Override
public void run() {
//handle the job here...
//using the synchronization point
synchronize(myClass.lock) {
}
}
}
static final int NUM_THREADS = 10;
public void executeSeveralJobs() {
ExecutorService executorService = Executors.newFixedThreadPool(NUM_THREADS);
MyClass myClass = new MyClass();
executorService.execute(new Job(myClass));
executorService.execute(new Job(myClass));
//initialize the jobs and add them to the ExecutorService
//...
executorService.shutdown();
//...
}
}
My multi-threaded application has a main class that creates multiple threads. The main class will wait after it has started some threads. The runnable class I created will get a file list, get a file, and remove a file by calling a web service. After the thread is done it will notify the main class to run again. My problem is it works for a while but possibly after an hour or so it will get to the bottom of the run method from the output I see in the log and that is it. The Java process is still running but it does not do anything based on what I am looking at in the log.
Main class methods:
Main method
while (true) {
// Removed the code here, it was just calling a web service to get a list of companies
// Removed code here was creating the threads and calling the start method for threads
mainClassInstance.waitMainClass();
}
public final synchronized void waitMainClass() throws Exception {
// synchronized (this) {
this.wait();
// }
}
public final synchronized void notifyMainClass() throws Exception {
// synchronized (this) {
this.notify();
// }
}
I originally did the synchronization on the instance but changed it to the method. Also no errors are being recorded in the web service log or client log. My assumption is I did the wait and notify wrong or I am missing some piece of information.
Runnable Thread Code:
At the end of the run method
// This is a class member variable in the runnable thread class
mainClassInstance.notifyMainClass();
The reason I did a wait and notify process because I do not want the main class to run unless there is a need to create another thread.
The purpose of the main class is to spawn threads. The class has an infinite loop to run forever creating and finishing threads.
Purpose of the infinite loop is for continually updating the company list.
I'd suggest moving from the tricky wait/notify to one of the higher-level concurrency facilities in the Java platform. The ExecutorService probably offers the functionality you require out of the box. (CountDownLatch could also be used, but it's more plumbing)
Let's try to sketch an example using your code as template:
ExecutorService execSvc = Executors.newFixedThreadPool(THREAD_COUNT);
while (true) {
// Removed the code here, it was just calling a web service to get a list of companies
List<FileProcessingTask> tasks = new ArrayList<FileProcessingTask>();
for (Company comp:companyList) {
tasks.add(new FileProcessingTask(comp));
}
List<Future<FileProcessingTask>> results = execSvc.invokeAll(tasks); // This call will block until all tasks are executed.
//foreach Future<FileProcessingTask> in results: check result
}
class FileProcessingTask implements Callable<FileResult> { // just like runnable but you can return a value -> very useful to gather results after the multi-threaded execution
FileResult call() {...}
}
------- edit after comments ------
If your getCompanies() call can give you all companies at once, and there's no requirement to check that list continuously while processing, you could simplify the process by creating all work items first and submit them to the executor service all at once.
List<FileProcessingTask> tasks = new ArrayList<FileProcessingTask>();
for (Company comp:companyList) {
tasks.add(new FileProcessingTask(comp));
}
The important thing to understand is that the executorService will use the provided collection as an internal queue of tasks to execute. It takes the first task, gives it to a thread of the pool, gathers the result, places the result in the result collection and then takes the next task in the queue.
If you don't have a producer/consumer scenario (cfr comments), where new work is produced at the same time that task are executed (consumed), then, this approach should be sufficient to parallelize the processing work among a number of threads in a simple way.
If you have additional requirements why the lookup of new work should happen interleaved from the processing of the work, you should make it clear in the question.
I have a singleton in Android for data loaded from xml. It gets recycled from time to time and I don't understand why. Singleton should exist through the lifetime of app process by my knowledge. Here's my singleton:
public class DataLib {
public static CategoryList categories = new CategoryList();
public static RegionList regions = new RegionList();
public static CompanyTypeList types = new CompanyTypeList();
public static SearchData searchData = new SearchData();
public static CompaniesList companies = new CompaniesList();
private static RegionData currentRegion;
private static final DataLib INSTANCE = new DataLib();
protected DataLib() {
}
public static DataLib getInstance() {
return INSTANCE;
}
public static void loadData() {
loadCategories();
loadRegions();
loadTypes();
}
/* ... some more static functions are here ...*/
}
As you can see it is not instantiated by any activity directly but rather by the process itself. The data are loaded by calling DataLib.loadData() when the application starts = activity which will end when the data are loaded.
I cannot tell for sure what triggers the recycling - sometimes app needs to stay in the background for longer time, sometimes it's in a few minutes. I am logging the pointer of the DataLib class so I can tell that it truly changed = got recycled.
Any ideas? Thanks.
EDIT: Answer is partially in marked answer + comments to it.
It gets recycled from time to time and I don't understand why.
Android will terminate your process "from time to time".
sometimes app needs to stay in the background for longer time, sometimes it's in a few minutes
The OS and the user can get rid of your process whenever they feel like it. Singletons and other static data members need to be caches for persistent data, loading that data using background threads and the like.
If there is particular work that you are doing in the background, you should be using a Service for that, to indicate to the OS that you are doing work in the background independent of any activities. That does not prevent Android from terminating your process (e.g., at user request), but it will make it a bit less likely to terminate your process on its own (i.e., the OS will tend to choose other processes).