简体   繁体   English

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

[英]How to synchronize non static method variable (object) in java

I have one method which write to a file. 我有一种写入文件的方法。 I need to synchronize file object 我需要同步文件对象

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;
    }


    }

But above code won`t take lock exclusive lock on file object as another instance of this class can have lock on this class and write to file. 但是上面的代码不会在文件对象上获得排他锁,因为此类的另一个实例可以在该类上具有锁并写入文件。 So I want to how handle this case ? 那么我想如何处理这种情况? I found one workaround creating a temporary file name appending time stamp (so temporary file name will be always unique) and after writing content to it , will first delete original file and then rename temporary file to original file name. 我发现一种解决方法是创建一个附加时间戳的临时文件名(因此临时文件名将始终是唯一的),并且在向其写入内容后,将首先删除原始文件,然后将临时文件重命名为原始文件名。

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

You are creating new File object ( alertFile ) every time method is run, so the lock does nothing as it is different every time method is run - you need to have static File instance shared across all method calls. 每次运行方法时都在创建新的File对象( alertFile ),因此该锁没有作用,因为每次运行方法时锁都不同-您需要在所有方法调用之间共享静态File实例。

If path can be different every time the method is run, you could create static Map<String, File> instance and use it like this: 如果每次运行该方法时path都可以不同,则可以创建static Map<String, File>实例并按如下方式使用它:

  1. Get path of the file. 获取文件的路径。
  2. If there is no File associated with this path, create it. 如果没有与此路径关联的File ,请创建它。
  3. Otherwise, recover existing File instance from map. 否则,请从映射中恢复现有的File实例。
  4. Use this File as a lock and do operations on it. 将此File用作锁并对其执行操作。

Example based on modified answer: 基于修改后答案的示例:

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;
    }


}

Your program does not get exclusive lock on file because you are using synchronized on a local variable alertFile that is not shared between instances of the class MessageFile (each object has its own alertFile ). 您的程序不会获得文件的独占锁定,因为您正在对本地变量alertFile使用synchronized ,该alertFile在类MessageFile实例之间不共享(每个对象都有其自己的alertFile )。 You have two possibilities to solve this: 您可以通过两种方法解决此问题:

1- Create some static object and synchronize on it (you may use fileName as it is already there). 1-创建一些静态对象并对其进行同步(您可以使用fileName因为它已经存在)。

2- Having a references in all the objects that point to the same object (passed in the constructor, for example) and synchronize on it. 2-在所有指向同一对象的对象中都有一个引用(例如,在构造函数中传递),并对其进行同步。

Synchronize on the class level object ie MessageFile.class or use a static synchronize method wrtietofile() . 在类级别的对象(即MessageFile.class)上同步或使用静态同步方法wrtietofile()。 it will make sure only one thread writes into the file at a time . 这样可以确保一次只有一个线程写入文件。 it also guarantees the lock will be released once the entire data is written to the file by a thread . 它也保证一旦线程将全部数据写入文件后,锁定将被释放。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM