patternjavaMinor
Loading an Object from File with Type-Safety and Thread-Safe access
Viewed 0 times
filewithobjecttypesafetyloadingthreadsafeandfrom
Problem
I'm attempting to write a bit of code that allows for easy and safe access to objects in a file. It seems to work great but I was curious if there was an easier way to do this or if Java already has something like this. If there isn't anything like this any critiques of my code would be appreciated as I'm trying to learn to be a better Java programmer.
The main objectives I have are...
loadFile is just a basic implementation of using a Loader, this code assumes those three files contain a Map object in the first, a Set object in the second, and a Set object in the third. You can either make those files using any standard method or else using the FileHandler class.
The FileHandler class is used to handle file reads and writes in a thread safe way.
```
public class FileHandler {
private static Set fileSet = Collections.synchronizedSet(new HashSet());
private final ReentrantReadWriteLock readWriteLock;
private final Lock read;
private final Lock write;
private final File file;
/**
* Creates a new thread-safe FileHandler for reading and wri
The main objectives I have are...
- Modularity (I want to be able to load any object type)
- Type-safety (I want all the object returned to be of the correct type give no warnings)
- Thread-safety (I want to be able to read and write multiple files, multiple times, concurrently)
loadFile is just a basic implementation of using a Loader, this code assumes those three files contain a Map object in the first, a Set object in the second, and a Set object in the third. You can either make those files using any standard method or else using the FileHandler class.
private void loadFiles() {
long time = System.currentTimeMillis();
Loader, Map> loader1 = new Loader, Map>(new File("file1.bin"), object1);
Loader, Set> loader2 = new Loader, Set>(new File("file2.bin"), object2);
Loader, Set> loader3 = new Loader, Set>(new File("file3.bin"), object3);
boolean OK1 = loader1.load();
boolean OK2 = loader2.load();
boolean OK3 = loader3.load();
if(OK1) {
object1 = loader1.getVariable();
}
if(OK2) {
object2 = loader2.getVariable();
}
if(OK3) {
object3 = loader3.getVariable();
}
System.out.println("File load took " + (System.currentTimeMillis() - time) + "ms.");
}The FileHandler class is used to handle file reads and writes in a thread safe way.
```
public class FileHandler {
private static Set fileSet = Collections.synchronizedSet(new HashSet());
private final ReentrantReadWriteLock readWriteLock;
private final Lock read;
private final Lock write;
private final File file;
/**
* Creates a new thread-safe FileHandler for reading and wri
Solution
-
The
-
Instead of printing error messages you should use a logger framework (for example, SLF4J and Logback). See: log4j vs. System.out.println - logger advantages?
Some notes about the current code:
-
The static
-
Do not rely on the finalize method. Make the releasing explicit. For example, create a
-
In the
-
Consider throwing a non-
-
You should check parameters for validity. The majority of the methods and constructors should check at least
The
Loader class could use Java's built-in ExecutorService with a Callable and a Future instead of reinventing the wheel. See: Effective Java Second Edition, Item 47: Know and use the libraries-
Instead of printing error messages you should use a logger framework (for example, SLF4J and Logback). See: log4j vs. System.out.println - logger advantages?
Some notes about the current code:
-
The static
fileSet field in the FileHandler class makes testing really hard. Actually, this class does not fulfill the Single Responsibility Principle. It loads/saves the objects and stores the handled files. I'd separate it to two class. One (FileStorage, for example) is responsible for loading and saving and another class creates FileStorage instances and checks that there is no more than one FileStorage instance for the same file.-
Do not rely on the finalize method. Make the releasing explicit. For example, create a
close() method in the FileHandler which unregisters the file and sets a flag/sets the file field to null. Then check the flag in the loadObject and saveObject methods. If the flag is set throw an IllegalStateException. See Effective Java Second Edition, Item 7: Avoid finalizers.-
In the
Loader.load method I'd use guard clauses:public boolean load() {
if (!file.exists()) {
return false;
}
try {
handler = new FileHandler(file);
} catch (IllegalArgumentException e) {
return false;
}
fileLoader = new FileLoader(handler, variable);
thread = new Thread(fileLoader);
thread.start();
return true;
}-
Consider throwing a non-
RuntimeException (a custom Exception subclass, not an IllegalArgumentException) when a client tries to create a FileHandler multiple times for the same file. Another idea is returning the former FileHandler again instead of throwing an exception, since FileHandler is thread-safe.-
You should check parameters for validity. The majority of the methods and constructors should check at least
null input references. See Effective Java Second Edition, Item 38: Check parameters for validityCode Snippets
public boolean load() {
if (!file.exists()) {
return false;
}
try {
handler = new FileHandler(file);
} catch (IllegalArgumentException e) {
return false;
}
fileLoader = new FileLoader<G, F>(handler, variable);
thread = new Thread(fileLoader);
thread.start();
return true;
}Context
StackExchange Code Review Q#12299, answer score: 2
Revisions (0)
No revisions yet.