gpt4 book ai didi

java - 当数据可用时,如何从 map 获取数据?

转载 作者:行者123 更新时间:2023-12-02 06:19:36 24 4
gpt4 key购买 nike

我在代码中使用 Java Callable Future。下面是我的主要代码,它使用了 future 和 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();
}
}

下面是我的 Task 类,它实现了 Callable 接口(interface),该类需要从 ClientData 类方法获取数据。我有一个后台线程,它使用 setter 在 ClientData 类中设置数据。

class Task implements Callable<String> {

public String call() throws Exception {

//.. some code

String hostname = ClientData.getPrimaryMapping("some_string").get(some_number);

//.. some code
}
}

下面是我的后台线程,它通过解析来自 URL 的数据来设置我的 ClientData 类中的值,并且每 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 的数据。同时,它将进入我的 Task 类的 call 方法。下面这行会抛出异常,为什么?因为我的后台线程仍在解析数据,并且尚未设置该变量。

String hostname = ClientData.getPrimaryMapping("some_string").get(some_number);

如何避免这个问题?有没有更好、更有效的方法来做到这一点?

最佳答案

您只想让任务等到 map 的第一次更新发生后再继续吗?

public class ClientData {

private static final AtomicReference<Map<String, Map<Integer, String>>> primaryMapping = new AtomicReference<>();
private static final CountDownLatch hasBeenInitialized = new CountDownLatch(1);

public static Map<String, Map<Integer, String>> getPrimaryMapping() {
try {
hasBeenInitialized.await();
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
return primaryMapping.get();
}

public static void setPrimaryMapping(Map<String, Map<Integer, String>> map) {
primaryMapping.set(map);
hasBeenInitialized.countDown();
}
}

一种更简单、更有效的方法,不会导致同步检查,也不会让你处理愚蠢的 InterruptedException 作为受检异常,可能是在启动多线程引擎之前简单地将初始值加载到 Map 中......

关于java - 当数据可用时,如何从 map 获取数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21126905/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com