I have a simple interface
public interface Text {
String asText() throws IOException;
}
And one implementation
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;
}
}
This class is very simple, it reads text from a file then returns it as a string. In order to avoid reading from the file multiple times I want to create a second class that will decorate the original one
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;
}
}
And now it work; however the result is muttable, and in order to work correctly with multiple threads i have created another decorator
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();
}
}
}
But now my program will spend resources on synchronization each time I call asText() .
What is the best implementation of a caching mechanism in my situation?
I would suggest making your cached class synchronized via the Double Check Lock mechanism, instead of using the additional implementation for thread safety:
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;
}
}
There might be concerns using the DCL as seen here- but if they exist on your end, just comment and I'll post additional support (I believe that modern JVMs are better suited for handling DCLs).
This should be good for your needs.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With