在虚拟机中为单个线程锁定文件。
在虚拟机中为单个线程锁定文件。
我有多个线程在将我的“Data”对象序列化为文件。
文件名基于对象中的2个字段。
class Data {org.joda.DateTime time;
String title;
public String getFilename() {
return time.toString() + \'_\' + title + \".xml\";
}
可能会有2个Data对象具有相同的“time”和“title”,因此具有相同的文件名。
这是可接受的,我很高兴任何一个都可以被保存(如果这些内容相同,则它们可能是相同的Data对象)。
我的问题是两个(或更多)线程同时写入文件,导致XML格式不正确。
我查看了java.nio.channels.FileLock,但它是用于虚拟机范围锁定,不适用于线程内部锁定。
我可以在DataIO.class上进行同步(但这将导致巨大的开销,因为我只想在各个文件上同步)。
在文件对象上同步将是无用的,因为多个文件对象可以表示相同的系统文件。
以下是代码:
class DataIO {public void writeArticleToFile(Article文章, String filename, boolean overwrite) throws IOException {
File file = new File(filename);
writeArticleToFile(article, file, overwrite);
}
public void writeDataToFile(Data data, File file, boolean overwrite) throws IOException {
if (file.exists()) {
if (overwrite) {
if (!file.delete()) {
throw new IOException(\"无法删除文件以进行覆盖写入:\" + file);
}
} else {
throw new IOException(\"文件\" + file + \"已存在,且覆盖标志已设置为false。\");
}
}
File parentFile = file.getParentFile();
if (parentFile != null) {
file.getParentFile().mkdirs();
}
file.createNewFile();
if (!file.canWrite()) {
throw new IOException(\"您无权写入文件:\" + file);
}
FileOutputStream fos = new FileOutputStream(file, false);
try {
writeDataToStream(data, fos);
logger.debug(\"成功将文章写入文件:\" + file.getAbsolutePath());
} finally {
fos.close();
}
}
}
如果我理解正确,您有一个表示单个文件的 Data 对象。
您可以考虑创建一个基于 Data 对象的分段集合。可能有一个 ConcurrentHashMap
的映射关系为
ConcurrentMap lockMap = new ConcurrentHashMap();
当您想写入此对象时,可以执行:
Lock lock = lockMap.get(someMyDataObject); lock.lock(); try{ //write object here }finally{ lock.unlock(); }
请记住,您需要根据标题和日期时间编写 hashCode 和 equals 方法。