【问题标题】:Simple Cache mechanizm using decorators使用装饰器的简单缓存机制
【发布时间】:2018-09-13 13:23:49
【问题描述】:

我有一个简单的界面

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() 时都会在同步上花费资源。

在我的情况下,缓存机制的最佳实现是什么?

【问题讨论】:

  • 如果你想让它线程安全,只需使用 synchronized 关键字

标签: java caching synchronization decorator


【解决方案1】:

我建议通过双重检查锁定机制使您的缓存类同步,而不是使用额外的线程安全实现:

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)。

这应该可以满足您的需求。

【讨论】:

    猜你喜欢
    • 2015-07-29
    • 1970-01-01
    • 2019-02-19
    • 2015-03-10
    • 1970-01-01
    • 1970-01-01
    • 2022-09-29
    • 2017-03-21
    • 1970-01-01
    相关资源
    最近更新 更多