I am using Java Callable Future in my code. Below is my main code which uses the future and callables -
public class TimeoutThread {
public static void main(String[] args) throws Exception {
// starting the background thread
new ScheduledCall().startScheduleTask();
ExecutorService executor = Executors.newFixedThreadPool(5);
Future<String> future = executor.submit(new Task());
try {
System.out.println("Started..");
System.out.println(future.get(3, TimeUnit.SECONDS));
System.out.println("Finished!");
} catch (TimeoutException e) {
System.out.println("Terminated!");
}
executor.shutdownNow();
}
}
Below is my Task
class which implements the Callable interface and this class needs to get the data from the ClientData
class method. And I have a background thread which is setting the data in ClientData
class by using the setters.
class Task implements Callable<String> {
public String call() throws Exception {
//.. some code
String hostname = ClientData.getPrimaryMapping("some_string").get(some_number);
//.. some code
}
}
Below is my background thread which is setting the value in my ClientData
class by parsing the data coming from the URL and it is running every 10 minutes.
public class ScheduledCall {
private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
public void startScheduleTask() {
final ScheduledFuture<?> taskHandle = scheduler.scheduleAtFixedRate(
new Runnable() {
public void run() {
try {
callServers();
} catch(Exception ex) {
ex.printStackTrace();
}
}
}, 0, 10, TimeUnit.MINUTES);
}
private void callServers() {
String url = "url";
RestTemplate restTemplate = new RestTemplate();
String response = restTemplate.getForObject(url, String.class);
parseResponse(response);
}
// parse the response and set it.
private void parseResponse(String response) {
//...
ConcurrentHashMap<String, Map<Integer, String>> primaryTables = null;
//...
// store the data in ClientData class variables which can be
// used by other threads
ClientData.setPrimaryMapping(primaryTables);
}
}
And below is my ClientData
class
public class ClientData {
private static final AtomicReference<Map<String, Map<Integer, String>>> primaryMapping = new AtomicReference<>();
public static Map<String, Map<Integer, String>> getPrimaryMapping() {
return primaryMapping.get();
}
public static void setPrimaryMapping(Map<String, Map<Integer, String>> map) {
primaryMapping.set(map);
}
}
PROBLEM STATEMENT:-
The only problem I am facing is, whenever I am starting the program for the first time, what will happen is, it will start the background thread which will parse the data coming from the URL. And simultaneously, it will go into call
method of my Task
class. And the below line will throw an exception, why? bcoz my background thread is still parsing the data and it hasn't set that variable.
String hostname = ClientData.getPrimaryMapping("some_string").get(some_number);
How do I avoid this problem? Is there any better and efficient way to do this?