我有一个方法可以写入文件。我需要同步文件对象
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>
实例并像这样使用它:
- 获取文件的路径
- 如果没有与此路径关联的
File
,请创建它 - 否则,请从映射中恢复现有的
File
实例 - 将此
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((。它将确保一次只有一个线程写入文件。它还保证一旦线程将整个数据写入文件,锁就会被释放。