gpt4 book ai didi

java - 如何在第一次调用 Singleton 期间仅更新一次 map ?

转载 作者:行者123 更新时间:2023-12-01 08:51:57 25 4
gpt4 key购买 nike

我必须在服务器上进行 HTTP 调用后解析响应。如果响应不成功,则尝试另一台服务器,否则解析成功的响应并填充两个 ConcurrentHashMap 并跳出 for 循环。所有服务器都会以相同的格式给出相同的准确响应。

下面是我的单例类,它在 ProcConfig 的构造函数中第一次调用时,调用 loadConfig() 方法来初始化所有内容,然后检查是否 addressToIdMapping map 中是否有一个条目。如果它不存在,那么它会抛出异常。之后,它启动一个后台线程,每 30 分钟调用一次 loadConfig() 方法来更新 addressToIdMappingprocessToTcpMapping 映射。

public class ProcConfig {
private static final Splitter SPLITTER = Splitter.on(',').trimResults().omitEmptyStrings();
private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
private final Map<String, Short> addressToIdMapping = new ConcurrentHashMap<>();
private final Map<DatacenterEnum, List<String>> processToTcpMapping = new ConcurrentHashMap<>();

private static class Holder {
private static final ProcConfig INSTANCE = new ProcConfig();
}

public static ProcConfig getInstance() {
return Holder.INSTANCE;
}

private ProcConfig() {
loadConfig();
checkArgument(!MapUtils.isEmpty(addressToIdMapping), "cannot find id, found '%s'.", addressToIdMapping);
scheduler.scheduleAtFixedRate(new Runnable() {
public void run() {
try {
loadConfig();
} catch (Exception ex) {
// log error
}
}
}, 60, 30, TimeUnit.MINUTES);
}

private void loadConfig() {
// current ipAddress where the program is running
Optional<String> ipAddress = Utils.getIPAddress();
List<String> servers = getServers();
for (String server : servers) {
try {
String response = HttpClient.getInstance().execute(makeUrl(server));
if (Strings.isNullOrEmpty(response) || response.equalsIgnoreCase("KEEP OUT")
|| response.equalsIgnoreCase("NOTHING FOUND")) {
continue;
}
parseConfig(response, ipAddress.get());
break;
} catch (Exception ex) {
// log error
}
}
}

private void parseConfig(final String response, final String ipAddress) throws IOException {
List<String> lines = IOUtils.readLines(new StringReader(response));
for (String line : lines) {
if (line.contains(ipAddress)) {
List<String> config = SPLITTER.splitToList(line);
Short id = Short.parseShort(config.get(2));
// this map will only have one entry for the ip address where it is running
addressToIdMapping.put(ipAddress, id);
} else if (line.contains("process_")) {
List<String> config = SPLITTER.splitToList(line);
String procAddr = config.get(0);
int datacenter = Integer.parseInt(config.get(1));
int portNumber = Integer.parseInt(config.get(3));
int numberOfPorts = Integer.parseInt(config.get(4));
DatacenterEnum colo = Utils.isProd() ? DatacenterEnum.name((byte) datacenter) : DatacenterEnum.DEV;
List<String> address = makeTcpAddress(procAddr, colo, portNumber, numberOfPorts);
processToTcpMapping.put(colo, address);
}
}
}

public Optional<Short> getId() {
Optional<String> ipAddress = Utils.getIPAddress();
return Optional.fromNullable(addressToIdMapping.get(ipAddress.get()));
}
}

现在我的问题是:我只想在第一次调用单例期间更新我的 addressToIdMapping 映射一次,以便 getId() 方法始终返回期间的内容 map 中的第一次更新。但现在它会在每次更新 30 分钟后返回 map 中的任何内容。例如:当第一次调用此类时,它将更新映射,因此我想在 addressToIdMapping 映射中永远保留相同的值,直到程序运行。这可以吗?正如你所看到的,我在我的构造函数中做了很多事情。与我正在做的事情相比,有没有更好的方法来做同样的事情?

一般来说,addressToIdMapping 映射始终只有一个用于运行代码的 IP 地址的条目。如果 processToTcpMapping 映射每 30 分钟更新一次,我就没事了.

最佳答案

您可以在ConcurrentHashMap上使用putIfAbsent方法,请参阅documentation

只有在条目不存在时才会更新该条目,这意味着一个 IP 地址的条目只会更新一次。

关于java - 如何在第一次调用 Singleton 期间仅更新一次 map ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42332631/

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