今天在公司做项目的时候,遇到了对文件的读写。在Java中,如果我们要读文件,虽然我们已经拿到了文件的引用,我们对这个文件进行了读操作,但是另外一个线程同时和可以获得这个文件的引用,对这个文件进行些操作。所以这样的结果就是我们读到的文件不是一个完整的文件,可能是一个老文件和新文件的综合体。所以我们要对文件进行加锁操作。
下面是文件操作的代码
package com.file.test;
import java.io.File;
import java.net.URI;
import java.util.Hashtable;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class LockFile extends File{
private static Hashtable<String , ReentrantReadWriteLock> locks = new Hashtable<String , ReentrantReadWriteLock>();
private ReentrantReadWriteLock lock = null;
public LockFile(File arg0, String arg1) {
super(arg0, arg1);
lock = initLock(this.getAbsolutePath());
}
public LockFile(String arg0, String arg1) {
super(arg0, arg1);
lock = initLock(this.getAbsolutePath());
}
public LockFile(String arg0) {
super(arg0);
lock = initLock(this.getAbsolutePath());
}
public LockFile(URI arg0) {
super(arg0);
lock = initLock(this.getAbsolutePath());
}
/*
* 这里要注意使用 static synchronized,不然可能同时有多个进行初始化这个文件
*/
private static synchronized ReentrantReadWriteLock initLock(String path) {
ReentrantReadWriteLock lock = locks.get(path);
if (lock == null) {
lock = new ReentrantReadWriteLock();
locks.put(path, lock);
}
return lock;
}
public ReentrantReadWriteLock getLock() {
return lock;
}
其实上面代码很简单,对文件进行了扩展,然后使用了ReentrantReadWriteLock,对文件进行加锁。这样就能处理读写的问题了。在我们每一次读文件的时候,我们获取readlock,然后进行加锁,读后解锁。对于写的情况也是类似。
下面顺便附上测试的代码
package com.file.test;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Random;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class LockFileTest {
private static final String FILE = "text.txt";
public static void main(String args[]) {
LockFileTest instance = new LockFileTest();
instance.run();
}
private void run() {
ReaderThread reader1 = new ReaderThread();
ReaderThread reader2 = new ReaderThread();
WriterThread writer1 = new WriterThread();
WriterThread writer2 = new WriterThread();
reader1.start();
reader2.start();
writer1.start();
writer2.start();
}
class ReaderThread extends Thread {
public void run() {
while (true) {
String pre = null;
LockFile file = new LockFile(FILE);
if (!file.exists()) continue;
ReentrantReadWriteLock lock = file.getLock();
lock.readLock().lock();
try {
BufferedReader reader = new BufferedReader(new FileReader(file));
String line = reader.readLine();
while (line != null) {
if (pre == null) {
pre = line;
}
else {
if (!pre.equals(line)) {
System.out.println("read wrong");
}
}
line = reader.readLine();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
lock.readLock().unlock();
}
}
}
class WriterThread extends Thread {
Random random = new Random();
public void run() {
String s = String.valueOf(Math.abs(random.nextInt()));
LockFile file = new LockFile(FILE);
ReentrantReadWriteLock lock = file.getLock();
lock.writeLock().lock();
try {
BufferedWriter writer = new BufferedWriter(new FileWriter(file));
for (int i=0 ; i<1000 ; i++) {
for (int j=0 ; j<1000 ; j++) {
writer.write(s + System.getProperty("line.separator"));
}
}
writer.flush();
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
lock.writeLock().unlock();
}
}
}
测试代码的逻辑也很简单。写的时候,就往一个文件里面写1000000行同样的字符,这里是使用随机函数生成的数字。读的时候,就看这个文件的1000000是不是都是一样的。这样就能测试文件的加锁是不是可以的。
明天讲写有关WeakReference的内容。