如何在java中同步非静态方法变量(对象)



我有一个方法可以写入文件。我需要同步文件对象

class MessageFile{
public static final String  fileName="Main.html"
@AutoWired
AppConifg appconfig;
 public boolean writeToFile(String fileContent) throws  Exception{
        String path = appConfig.getNewsPath() + File.separator + fileName; // getNewsPath is non-static method
        final  File alertFile= new File(path);
        FileOutputStream out = null;
        synchronized (alertFile) {
          if (!alertFile.exists()) {
              alertFile.createNewFile();
          }
          try {
              out = new FileOutputStream(alertFile, false);
              out.write(fileContent.getBytes());
              out.flush();
          } finally {
              if (out != null) {
                  out.close();
              }
          }
      }
        return true;
    }

    }

但上面的代码不会对文件对象使用锁独占锁,因为这个类的另一个实例可以对这个类使用锁并写入文件。所以我想如何处理这个案子?我找到了一个解决方法,创建一个附加时间戳的临时文件名(这样临时文件名将始终是唯一的(,在向其写入内容后,将首先删除原始文件,然后将临时文件重命名为原始文件名。

如果MessageFile.class是唯一访问该文件的对象,则可以尝试在它上进行同步。

您的程序不会获得文件的独占锁定,因为您在局部变量alertFile上使用synchronized,而该变量在类MessageFile的实例之间不共享(每个对象都有自己的alertFile(。你有两种可能性来解决这个问题:

1-创建一些静态对象并对其进行同步(您可以使用fileName,因为它已经存在(。

2-在所有指向同一对象的对象中都有一个引用(例如,在构造函数中传递(并对其进行同步。

每次运行方法时都要创建新的File对象(alertFile(,因此锁不会执行任何操作,因为每次运行方法都会有所不同-您需要在所有方法调用中共享静态File实例。

如果每次运行该方法时path可能不同,那么您可以创建static Map<String, File>实例并像这样使用它:

  1. 获取文件的路径
  2. 如果没有与此路径关联的File,请创建它
  3. 否则,请从映射中恢复现有的File实例
  4. 将此File用作锁并对其执行操作

基于修改答案的示例:

class MessageFile{
    public static final String  fileName="Main.html"
    @AutoWired
    AppConifg appconfig;
    private static final Map<String, File> filesMap = new HashMap<>();
    public boolean writeToFile(String fileContent) throws  Exception{
        String path = appConfig.getNewsPath() + File.separator + fileName; // getNewsPath is non-static method
        final File alertFile;
        synchronized(filesMap) {
            if (filesMap.containsKey(path)) {
                alertFile = filesMap.get(path);
            }
            else {
                alertFile = new File(path);
                filesMap.put(path, alertFile);
            }
        }
        FileOutputStream out = null;
        synchronized (alertFile) {
            if (!alertFile.exists()) {
                alertFile.createNewFile();
            }
            try {
                out = new FileOutputStream(alertFile, false);
                out.write(fileContent.getBytes());
                out.flush();
            } finally {
                if (out != null) {
                    out.close();
                }
            }
        }
        return true;
    }

}

在类级对象即MessageFile.class上同步或使用静态同步方法wrtietofile((。它将确保一次只有一个线程写入文件。它还保证一旦线程将整个数据写入文件,锁就会被释放。

最新更新