Question

Below is my Interface -

public interface IClient {
    public String read(ClientInput input);
}

This is my Implementation of the Interface -

public class TempClient implements IClient {

    @Override
    public String read(ClientInput input) {

    }
}

Below is my factory code -

public class TempClientFactory {

    public static IClient getInstance() {
    new TempScheduler().startScheduler();
    return ClientHolder.INSTANCE;
    }

    private static class ClientHolder {
        private static final TempClient INSTANCE = new TempClient();
    }
}

Now I have a factory which gets the instance of TempClient like this so customer will use our factory like below while making the call to our code.

IClient client = TempClientFactory.getInstance();
client.read(input);

And below is my background thread code -

public class TempScheduler {

    private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);

        public void startScheduler() {
            final ScheduledFuture<?> taskHandle = scheduler.scheduleAtFixedRate(new Runnable() {
                public void run() {
                try {
                    callServers();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
                }
            }, 0, 10L, TimeUnit.MINUTES);
        }
    }

    //... some code
}

Problem Statement:-

  1. Now I have a background thread which will be running behind the scene which fetches the data from the URL, parses it and stores it in a variable. Now what I want is as soon as our customer starts making a call to use our code by using the factory, I want the background thread to get started. So I decided to put that call in my above TempClientFactory and it is working perfectly fine..

Now problem with that approach is, customer will keep on calling my TempClientFactory so it will keep on starting the background thread always.. What I am looking for is, if the background thread is started once, then I don't want to start it again from another thread but it should keep on running every 10 minutes behind the scene as it already got started first time.

If my understanding is right, suppose if I am calling my TempClientFactory once, then it will start the background thread and my background thread will keep on running every 10 minutes.. And if I am calling my factory again, then it will start the same background again which will also run every 10 minutes as well? Or it will start only one background thread which will run every 10 minutes?

Was it helpful?

Solution

You'll need to manually prevent it from being called again. You could add a static block to the inner class.

public class TempClientFactory {
    public static IClient getInstance() {
        return ClientHolder.INSTANCE;
    }

    private static class ClientHolder {
        private static final TempClient INSTANCE = new TempClient();

        static {
            // You could do this here, as well, if it were more complicated
            //  than a one-line statement (e.g., requires try/catch):
            //INSTANCE = new TempClient();

            new TempScheduler().startScheduler();
        }
    }
}

Similarly to the thread safe, lazy loading that the JVM guarantees for instantiating the singleton, it will also guarantee one-time access to starting the scheduler here.

Therefore, you will only start, and schedule, your thread to be run once.

Also, I would recommend converting your ex.printStackTrace(); to an actual log statement.

OTHER TIPS

Use a singleton method which will ensure you a single instance of a class. to create object of TempScheduler just call

 public class TempClientFactory {

    public static IClient getInstance() 
   {

       TempScheduler  obj=TempScheduler.getTempScheduler(); 
       if(obj.flag==false) 
       {
        obj.startScheduler();
       }
       return ClientHolder.INSTANCE;
    }

    private static class ClientHolder {
        private static final TempClient INSTANCE = new TempClient();
    }
}






 public class TempScheduler {

            private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
            public static TempScheduler scheduler=null;
            public bool flag;

                public void startScheduler() {
                    flag=true;
                    final ScheduledFuture<?> taskHandle = scheduler.scheduleAtFixedRate(new Runnable() {
                        public void run() {
                        try {
                            callServers();
                        } catch (Exception ex) {
                            ex.printStackTrace();
                        }
                        }
                    }, 0, 10L, TimeUnit.MINUTES);
                }
            }

            private TempScheduler()
            {

            }

            synchronized public static TempScheduler getTempScheduler()
            {
             if(scheduler==null)
             {
                scheduler=new TempScheduler();
             }
             return scheduler;
           }


            //... some code
        }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top