Tengo un objeto responsable de la persistencia del estado JTable
en el disco. Guarda/carga columnas visibles, su tamaño, posición, etc. A continuación se incluyen algunos bits interesantes de su definición de clase.Acceso a archivos sincronizado en el objeto Java
class TableSaver {
Timer timer = new Timer(true);
TableSaver() {
timer.schedule(new TableSaverTimerTask(), 15000, SAVE_STATE_PERIOD);
}
synchronized TableColumns load(PersistentTable table) {
String xml = loadFile(table.getTableKey());
// parse XML, return
}
synchronized void save(String key, TableColumns value) {
try {
// Some preparations
writeFile(app.getTableConfigFileName(key), xml);
} catch (Exception e) {
// ... handle
}
}
private class TableSaverTimerTask extends TimerTask {
@Override
public void run() {
synchronized (TableSaver.this) {
Iterator<PersistentTable> iterator = queue.iterator();
while (iterator.hasNext()) {
PersistentTable table = iterator.next();
if (table.getTableKey() != null) {
save(table.getTableKey(), dumpState(table));
}
iterator.remove();
}
}
}
}
}
- Sólo existe una instancia de
TableSaver
, nunca. load()
pueden invocarse desde varios hilos. El temporizador es claramente otro hilo.loadFile()
ywriteFile()
no dejan cadenas abiertas de archivos: usan una biblioteca robusta, bien probada y ampliamente utilizada que siempre cierra las transmisiones contry ... finally
.
A veces esto falla con una excepción como:
java.lang.RuntimeException: java.io.FileNotFoundException: C:\path\to\table-MyTable.xml (The requested operation cannot be performed on a file with a user-mapped section open)
at package.FileUtil.writeFile(FileUtil.java:33)
at package.TableSaver.save(TableSaver.java:175)
at package.TableSaver.access$600(TableSaver.java:34)
at package.TableSaver$TableSaverTimerTask.run(TableSaver.java:246)
at java.util.TimerThread.mainLoop(Unknown Source)
at java.util.TimerThread.run(Unknown Source)
Caused by: java.io.FileNotFoundException: C:\path\to\table-MyTable.xml (The requested operation cannot be performed on a file with a user-mapped section open)
at java.io.FileOutputStream.open(Native Method)
at java.io.FileOutputStream.<init>(Unknown Source)
at java.io.FileOutputStream.<init>(Unknown Source)
at package.FileUtilWorker.writeFile(FileUtilWorker.java:57)
... 6 more
así que tengo dos preguntas:
- ¿Cómo puede este tipo de sincronización fallar? Tenga en cuenta que estoy seguro de que solo hay una instancia de
TableSaver
. - ¿Qué es esto en el stacktrace:
package.TableSaver.access$600(TableSaver.java:34)
? La línea 34 es la línea conclass TableSaver {
. ¿Puede ser esta la razón por la cual la sincronización no funciona?
puede publicar su 'writefile() 'código? –
Con respecto al n. ° 2, no hay problema. Eso es solo un artefacto de compilación de llamar a un miembro privado de la clase envolvente de una clase interna anidada. –