我有一个简单的界面
public interface Text {
String asText() throws IOException;
}
一个实现
public final class TextFromFile implements Text{
private final String path;
public TextFromFile(final String pth) {
this.path = pth;
}
@Override
public String asText() throws IOException {
final String text = Files.readAllLines(Paths.get(this.path))
.stream()
.collect(Collectors.joining(""));
return text;
}
}
这个类非常简单,它从文件中读取文本然后将其作为字符串返回。为了避免多次从文件中读取,我想创建一个将装饰原始文件的第二个类
public final class CachedText implements Text{
private final Text origin;
private String result;
public CachedText(final Text orgn) {
this.origin = orgn;
}
@Override
public String asText() throws IOException {
if(this.result == null){
this.result = this.origin.asText();
}
return this.result;
}
}
现在它起作用了;但result
是可变的,为了正确使用多个线程,我创建了另一个装饰器
public final class ThreadSafeText implements Text{
private final Text origin;
public ThreadSafeText(final Text orgn) {
this.origin = orgn;
}
@Override
public String asText() throws IOException {
synchronized(this.origin){
return this.origin.asText();
}
}
}
但现在我的程序每次拨打asText()
时都会在同步上花费资源。
在我的情况下,缓存机制的最佳实现是什么?
答案 0 :(得分:2)
我建议通过Double Check Lock机制使您的缓存类同步,而不是使用额外的线程安全实现:
public final class CachedText implements Text{
private final Text origin;
private String result;
public CachedText(final Text orgn) {
this.origin = orgn;
}
@Override
public String asText() throws IOException {
if(this.result == null){
synchronized(this) {
if(this.result == null){
this.result = this.origin.asText();
}
}
}
return this.result;
}
}
可能有人担心使用DCL here - 但如果它们存在于您的最后,只需发表评论,我会发布其他支持(我相信现代JVM更适合处理DCL)
这应该有利于您的需求。