需求:读写目标文件为同一个(是一张从摄像头拿到的数据存成的图片),读文件时候要确保没有在被写(否则可能拿到部不完整的数据)。高频写,低频读。
1、如网上所说,用FileLock,类似如下
FileOutputStream outStream = new FileOutputStream(file);//或者
outStream.getChannel().lock();
但是问题是这里的lock是channel的lock,同一个文件可以有多个channel,而我的读写不在同一个线程,没办法使用同一个channel。
2、使用信号量,直接上最终代码了,中间经历过优化,主要是tryAcquire和Acquire的区别。
import android.util.Log;
import java.io.File;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
public class FrameImageLock {
private static final String TAG = FrameImageLock.class.getSimpleName();
private Semaphore lock;
private File file;
private FrameImageLock() {
lock = new Semaphore(1);
file = new File(Constants.CURRENT_FRAME);
FileUtil.checkFileExistOrCreate(file);
}
private static class InstanceHolder {
public static FrameImageLock instance = new FrameImageLock();
}
public static FrameImageLock getInstance() {
return InstanceHolder.instance;
}
public File tryAcquire() {
try {
if (lock.tryAcquire(1000, TimeUnit.MILLISECONDS)) {
return file;
} else {
Log.e(TAG, ":timeout");
}
} catch (InterruptedException e) {
Log.e(TAG, ":interrupted");
}
return null;
}
public File acquireImmediately() {
try {
if (lock.tryAcquire(0, TimeUnit.MILLISECONDS)) {
return file;
} else {
Log.e(TAG, " file is in use");
}
} catch (InterruptedException ignored) {
}
return null;
}
public void release() {
lock.release();
}
}
一个方法,看下能不能拿到文件的使用权,能就用,不能就算了。另一个方法看看,不行就等1秒,超时再作罢。
可以实现:缺点,高频使用信号量(目标文件是摄像头数据,可能30FPS),性能问题。设计问题,只能针对性的保护目标文件。代码不能复用。
3、有大神教我用队列,和我文章开头说的读写频率不符合。弃之。
4、后续在看怎么优化,看到有人说用RandomAccessFile,还没了解