JavaREST优化数据结构访问
我有一个JavaREST应用程序,其中一个端点总是处理JavaREST优化数据结构访问,java,multithreading,concurrency,Java,Multithreading,Concurrency,我有一个JavaREST应用程序,其中一个端点总是处理ConcurrentMap。我正在做负载测试,当负载测试开始增加时,情况真的很糟糕 为了提高应用程序的效率,我可以实施哪些策略 我是否应该使用Jetty线程,因为它是我正在使用的服务器?还是主要是代码?或者两者都有 成为瓶颈的方法如下 基本上,我需要从给定的文件中读取一些行。我无法将其存储在数据库中,因此我提出了一个映射处理。但是,我知道,对于大型文件,不仅需要很长时间才能到达行,而且我还冒着这样的风险,即当地图有许多条目时,它将消耗大量内存
ConcurrentMap
。我正在做负载测试,当负载测试开始增加时,情况真的很糟糕
为了提高应用程序的效率,我可以实施哪些策略
我是否应该使用Jetty线程,因为它是我正在使用的服务器?还是主要是代码?或者两者都有
成为瓶颈的方法如下
基本上,我需要从给定的文件中读取一些行。我无法将其存储在数据库中,因此我提出了一个映射处理。但是,我知道,对于大型文件,不仅需要很长时间才能到达行,而且我还冒着这样的风险,即当地图有许多条目时,它将消耗大量内存
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);
}
公共字符串getLine(int-lineNr)引发IllegalArgumentException{
如果(线路编号>线路编号){
抛出新的IllegalArgumentException();
}
if(dict.containsKey(线路编号)){
返回dict.get(lineNr);
}
已同步(此){
try(Stream st=Files.lines(doc.toPath())
可选optionalLine=st.skip(lineNr-1).findFirst();
if(optionalLine.isPresent()){
dict.put(lineNr,optionalLine.get());
}否则{
nrLines=nrLines>lineNr?lineNr:nrLines;
抛出新的IllegalArgumentException();
}
}捕获(IOE异常){
e、 printStackTrace();
}
返回cache.get(lineNr);
}
将ConcurrentMap
与同步(此)
混为一谈可能不是正确的方法。java.util.concurrent包中的类是为特定用例设计的,并尝试在内部优化同步
相反,我建议首先尝试一个设计良好的缓存库,看看性能是否足够好。一个例子是。根据文档,它为您提供了一种声明如何加载数据的方法,即使是异步加载:
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));
AsyncLoadingCache缓存=caffee.newBuilder()
.最大尺寸(10_000)
.expireAfterWrite(10,时间单位:分钟)
//或者:使用包装为异步的同步计算构建
.buildAsync(键->createExpensiveGraph(键));
//或者:使用返回未来的异步计算构建
.buildAsync((键,执行器)->createExpensiveGraphAsync(键,执行器));
将ConcurrentMap
与同步(此)
混为一谈可能不是正确的方法。java.util.concurrent包中的类是为特定用例设计的,并尝试在内部优化同步
相反,我建议首先尝试一个设计良好的缓存库,看看性能是否足够好。一个例子是。根据文档,它为您提供了一种声明如何加载数据的方法,即使是异步加载:
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));
AsyncLoadingCache缓存=caffee.newBuilder()
.最大尺寸(10_000)
.expireAfterWrite(10,时间单位:分钟)
//或者:使用包装为异步的同步计算构建
.buildAsync(键->createExpensiveGraph(键));
//或者:使用返回未来的异步计算构建
.buildAsync((键,执行器)->createExpensiveGraphAsync(键,执行器));
此解决方案基于以下两个假设:
IllegalArgumentException
public String getLine(int lineNr) throws IllegalArgumentException {
if (lineNr > nrLines) {
throw new IllegalArgumentException();
}
return cache.computeIfAbsent(lineNr, (l) -> {
try (Stream<String> st = Files.lines(path)) {
Optional<String> optionalLine = st.skip(lineNr - 1).findFirst();
if (optionalLine.isPresent()) {
return optionalLine.get();
} else {
nrLines = nrLines > lineNr ? lineNr : nrLines;
throw new IllegalArgumentException();
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
});
}
公共字符串getLine(int-lineNr)引发IllegalArgumentException{
如果(线路编号>线路编号){
抛出新的IllegalArgumentException();
}
返回cache.computeIfAbsent(lineNr,(l)->{
try(Stream st=Files.lines(路径)){
可选optionalLine=st.skip(lineNr-1).findFirst();
if(optionalLine.isPresent()){
返回optionalLine.get();
}否则{
nrLines=nrLines>lineNr?lineNr:nrLines;
抛出新的IllegalArgumentException();
}
}捕获(IOE异常){
e、 printStackTrace();
}
返回null;
});
}
我通过生成3个线程“验证”了第二个假设,其中:
IllegalArgumentException
public String getLine(int lineNr) throws IllegalArgumentException {
if (lineNr > nrLines) {
throw new IllegalArgumentException();
}
return cache.computeIfAbsent(lineNr, (l) -> {
try (Stream<String> st = Files.lines(path)) {
Optional<String> optionalLine = st.skip(lineNr - 1).findFirst();
if (optionalLine.isPresent()) {
return optionalLine.get();
} else {
nrLines = nrLines > lineNr ? lineNr : nrLines;
throw new IllegalArgumentException();
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
});
}
公共字符串getLine(int-lineNr)引发IllegalArgumentException{
如果(线路编号>线路编号){
抛出新的IllegalArgumentException();
}