У меня есть объект, ответственный за сохранение состояния JTable
на диске. Он сохраняет/загружает видимые столбцы, их размер, положение и т.д. Ниже приведены несколько интересных бит из определения его класса.
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();
}
}
}
}
}
- Существует только один экземпляр
TableSaver
, когда-либо. -
load()
может быть вызван из многих потоков. Таймер - это еще один поток. -
loadFile()
иwriteFile()
не оставляют открытых потоков файлов - они используют надежную, хорошо протестированную и широко используемую библиотеку, которая всегда закрывает потоки с помощьюtry ... finally
.
Иногда это происходит с исключением, например:
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
У меня есть два вопроса:
- Как может произойти такая синхронизация? Обратите внимание, что я уверен, что существует только один экземпляр
TableSaver
. - Что это за штука в stacktrace:
package.TableSaver.access$600(TableSaver.java:34)
? Строка 34 - это строка сclass TableSaver {
. Может ли это быть причиной того, что синхронизация не работает?