加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

文件访问在Java对象上同步

发布时间:2020-12-14 05:09:43 所属栏目:Java 来源:网络整理
导读:我有一个对象负责持久化JTable状态到磁盘.它保存/加载可见列,它们的大小,位置等.其类定义中的一些有趣的位如下. class TableSaver { Timer timer = new Timer(true); TableSaver() { timer.schedule(new TableSaverTimerTask(),15000,SAVE_STATE_PERIOD); }
我有一个对象负责持久化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 …关闭流.

有时这样会失败,例如:

java.lang.RuntimeException: java.io.FileNotFoundException: C:pathtotable-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:pathtotable-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行是与类TableSaver {的行.这可能是同步不行的原因吗?

解决方法

Google了解我,这似乎是Windows具体的.以下是 Bug 6354433的摘录:

This is Windows platform issue with memory-mapped file,i.e. MappedByteBuffer. The Java 5.0 doc for FileChannel state that “the buffer and the mapping that it represents will remain valid until the buffer itself is garbage-collected”. The error occurs when we tried to re-open the filestore and the mapped byte buffer has not been GC. Since there is no unmap() method for mapped byte buffer (see bug 4724038),we’re at the mercy of the underlying operating system on when the buffer get free up. Calling System.gc() might free up the buffer but it is not guarantee. The problem doesn’t occurs on Solaris; may be due to the way shared memory is implemented on Solaris. So the work-around for Windows is not to use memory-mapped file for the transaction information tables.

你使用什么Java / Windows版本?它有最新的更新吗?

这里有两个相关的错误,有一些有用的见解:

> Bug 4715154 – 无法删除内存映射文件.
> Bug 4469299 – 内存映射文件未GC.

至于你的第二个问题,那就是内部或者匿名类的自动生成的类名.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读