我在我的代码中使用 Java Callable Future。以下是我使用未来和可调用对象的主要代码 -
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();
}
}
下面是我Task
的实现 Callable 接口的类,这个类需要从ClientData
类方法中获取数据。我有一个后台线程,它ClientData
使用设置器在类中设置数据。
class Task implements Callable<String> {
public String call() throws Exception {
//.. some code
String hostname = ClientData.getPrimaryMapping("some_string").get(some_number);
//.. some code
}
}
下面是我的后台线程,它ClientData
通过解析来自 URL 的数据来设置我的类中的值,它每 10 分钟运行一次。
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);
}
}
下面是我的ClientData
课
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);
}
}
问题陈述:-
我面临的唯一问题是,每当我第一次启动程序时,会发生什么,它将启动后台线程,该线程将解析来自 URL 的数据。同时,它将进入call
我的Task
课堂方法。下面的行会抛出异常,为什么?bcoz 我的后台线程仍在解析数据,它还没有设置该变量。
String hostname = ClientData.getPrimaryMapping("some_string").get(some_number);
我该如何避免这个问题?有没有更好更有效的方法来做到这一点?