5

以下方法属于实现 Runnable 的对象 A。它由对象 A 中的其他方法和 run 方法中的代码异步调用(因此,它是从其他线程调用的,周期为 5 秒)。

我最终会遇到文件创建异常吗?

如果我使方法同步...总是在对象 A 上获取锁?其中一个调用者在run()方法中的事实让我感到困惑:S

感谢您的投入。

private void saveMap(ConcurrentMap<String, String> map) {
    ObjectOutputStream obj = null;
    try {
        obj = new ObjectOutputStream(new FileOutputStream("map.txt"));
        obj.writeObject(map);

    } catch (IOException ex) {
        Logger.getLogger(MessagesFileManager.class.getName()).log(Level.SEVERE, null, ex);
    } finally {
        try {
            obj.close();
        } catch (IOException ex) {
            Logger.getLogger(MessagesFileManager.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    notifyActionListeners();
}
4

2 回答 2

6

同步实例方法使用this对象作为锁,并防止来自不同线程的所有同步实例方法(甚至其他)同时执行。

要回答有关同步要求的问题,答案基本上是肯定的,因为您有多个线程访问同一方法,因此输出可能会发生冲突。

作为设计评论,我会使用您的saveMap方法static,因为它不访问任何字段(它是无状态的),并且更强烈地表明文件的输出依赖于实例,因此文件输出可能会发生冲突更明显与其他实例。

编辑:

这是我建议的代码:

private static synchronized void saveMap(Map<String, String> map) {
    ...
}

仅供参考,static synchronized方法使用类对象(即 MyClass.class),它是一个单例,作为锁对象。

于 2012-05-12T23:51:28.407 回答
0

It's called asynchronously by other method from the object A and by code inside the run method (so, it's called from other thread, with a period of 5 seconds).

Given that saveMap is called from multiple threads, without synchronization you cannot guarantee that two threads won't try to write to the same file concurrently. This will cause an incorrectly-formatted file when it happens.

The simplest solution is to make the method synchronized.

private synchronized void saveMap(ConcurrentMap<String, String> map) { ... }

If the map is large enough, this may cause unresponsiveness in your program. Another option is to write to a temporary file (a new file each time it's called) and then use synchronization while swapping the new file over map.txt by renaming and deleting.

private void saveMap(ConcurrentMap<String, String> map) {
    File file = ... original code to write to a temporary file ...
    if (file != null) {
        synchronized(this) {
            ... move file over map.txt ...
        }
        notifyActionListeners();
    }
}

Keep in mind that swapping two files won't be an atomic operation. Any external program or thread from the same program may catch the short time that map.txt doesn't exist. I was unable to find an atomic file-swap method in Java, but maybe with some searching you will.

于 2012-05-13T00:02:56.907 回答