我有一个Java REST应用程序,其中一个端点始终处理ConcurrentMap
。我正在进行负载测试,当负载测试开始增加时,这确实很糟糕。
我可以实施哪些策略来提高应用程序的效率?
我应该使用Jetty线程吗,因为它是我正在使用的服务器?还是主要是代码?或两者?
成为瓶颈的方法如下。
基本上,我需要从给定文件中读取一些行。我无法将其存储在数据库中,因此我通过Map进行了此处理。但是,我知道对于大文件,不仅要花很长时间才能到达该行,而且我冒这样一个事实,即Map包含许多条目时会占用大量内存...dict
是ConcurrentMap
。
public String getLine(int lineNr) throws IllegalArgumentException {
if (lineNr > nrLines) {
throw new IllegalArgumentException();
}
if (dict.containsKey(lineNr)) {
return dict.get(lineNr);
}
synchronized (this) {
try (Stream<String> st = Files.lines(doc.toPath())
Optional<String> optionalLine = st.skip(lineNr - 1).findFirst();
if (optionalLine.isPresent()) {
dict.put(lineNr, optionalLine.get());
} else {
nrLines = nrLines > lineNr ? lineNr : nrLines;
throw new IllegalArgumentException();
}
} catch (IOException e) {
e.printStackTrace();
}
return cache.get(lineNr);
}
最佳答案
将ConcurrentMap
与synchronized(this)
混合可能不是正确的方法。 java.util.concurrent
包中的类是为特定用例设计的,并尝试在内部优化同步。
相反,我建议先尝试一个设计良好的缓存库,看看性能是否足够好。一个示例是Caffeine。根据Population文档,它为您提供了一种声明如何加载数据的方法,甚至是异步的:
AsyncLoadingCache<Key, Graph> cache = Caffeine.newBuilder()
.maximumSize(10_000)
.expireAfterWrite(10, TimeUnit.MINUTES)
// Either: Build with a synchronous computation that is wrapped as asynchronous
.buildAsync(key -> createExpensiveGraph(key));
// Or: Build with a asynchronous computation that returns a future
.buildAsync((key, executor) -> createExpensiveGraphAsync(key, executor));