下面列出了怎么用java.nio.channels.FileLock的API类实例代码及写法,或者点击链接到github查看源代码。
/**
* Gets an exclusive lock from a RandomAccessFile. Works because the file is writable.
* @param from beginning of the locked region
* @param size how many bytes to lock
* @return A lock object representing the newly-acquired lock
* @throws IOException if there is a problem creating the temporary file
*/
static FileLock getExclusiveLockFromRandomAccessFile(long from, long size) throws IOException {
Path path = Files.createTempFile("foo", "txt");
try (RandomAccessFile file = new RandomAccessFile(path.toFile(), "rw");
FileLock lock = file.getChannel()
.lock(from, size, false)) {
if (lock.isValid()) {
LOG.debug("This is a valid exclusive lock");
return lock;
}
return null;
} catch (Exception e) {
LOG.error(e.getMessage());
}
return null;
}
private static long writeDataToFile(File file, ChunkBuffer data,
long offset, boolean sync) {
final Path path = file.toPath();
return processFileExclusively(path, () -> {
FileChannel channel = null;
try {
channel = open(path, WRITE_OPTIONS, NO_ATTRIBUTES);
try (FileLock ignored = channel.lock()) {
return writeDataToChannel(channel, data, offset);
}
} catch (IOException e) {
throw new UncheckedIOException(e);
} finally {
closeFile(channel, sync);
}
});
}
/**
* Waits for a file lock for a given time, with a given frequency.
* Does nothing if cannot lock after totalTime - to avoid deadlocks
* @param f
* @param time
* @param totalTime
*/
public static void pauseForLock(File f, int frequency, int totalTime) throws Exception {
// If file locked, wait for up to 2s
int waited = 0;
final FileOutputStream out = new FileOutputStream(f);
try {
FileLock lock = out.getChannel().tryLock();
try {
while(lock==null) {
Thread.sleep(frequency);
waited+=frequency;
if (waited>=totalTime) break;
}
} finally {
if (lock!=null) lock.release();
}
} finally {
out.close();
}
}
/**
* Attempts to acquire an exclusive lock on the storage.
*
* @return A lock object representing the newly-acquired lock or
* <code>null</code> if storage is already locked.
* @throws IOException if locking fails.
*/
FileLock tryLock() throws IOException {
File lockF = new File(root, STORAGE_FILE_LOCK);
lockF.deleteOnExit();
RandomAccessFile file = new RandomAccessFile(lockF, "rws");
FileLock res = null;
try {
res = file.getChannel().tryLock();
} catch(OverlappingFileLockException oe) {
file.close();
return null;
} catch(IOException e) {
LOG.error("Cannot create lock on " + lockF, e);
file.close();
throw e;
}
return res;
}
private static <T> T withBlockingLock(File dexDir, File sourceApk, RunnableIO<T> r) throws IOException {
final long currentCrc = getZipCrc(sourceApk);
File lockFile = new File(dexDir, LOCK_FILE);
RandomAccessFile lockRaf = new RandomAccessFile(lockFile, "rw");
FileChannel lockChannel = null;
FileLock cacheLock = null;
try {
lockChannel = lockRaf.getChannel();
Log.v(TAG, "Waiting for lock on: " + lockFile.getAbsolutePath());
cacheLock = lockChannel.lock();
Log.v(TAG, "Locked " + lockFile.getPath());
long l = lockRaf.length() >= (Long.SIZE / 8) ? lockRaf.readLong() : 0;
long c = lockRaf.length() >= 2 * (Long.SIZE / 8) ? lockRaf.readLong() : 0;
return r.run(c != currentCrc || l != getTimeStamp(sourceApk));
} finally {
lockRaf.seek(0);
lockRaf.writeLong(getTimeStamp(sourceApk));
lockRaf.writeLong(currentCrc);
if (cacheLock != null)
cacheLock.release();
if (lockChannel != null)
lockChannel.close();
lockRaf.close();
Log.v(TAG, "Unlocked " + lockFile.getPath());
}
}
public GlobalHotkeyListener(TipsFrame tipsFrame) {
this.tipsFrame = tipsFrame;
for (HotkeyType hotKey : HotkeyType.values()) {
JIntellitype.getInstance().registerHotKey(hotKey.getIdentifier(), hotKey.getModifier(), hotKey.getKeycode());
}
// 禁止重复运行
try {
stream = new FileOutputStream(workingLockFile);
FileLock fileLock = stream.getChannel().tryLock();
if (fileLock == null) {
System.out.println("working");
System.exit(1);
}
} catch (FileNotFoundException ignore) {
} catch (IOException e) {
System.exit(1);
}
}
void replace(FileLock fromLock, FileLock toLock) {
// the lock must exist so there must be a list
List<FileLockReference> list = lockMap.get(fileKey);
assert list != null;
synchronized (list) {
for (int index=0; index<list.size(); index++) {
FileLockReference ref = list.get(index);
FileLock lock = ref.get();
if (lock == fromLock) {
ref.clear();
list.set(index, new FileLockReference(toLock, queue, fileKey));
locks.remove(fromLock);
locks.add(toLock);
break;
}
}
}
}
/**
* unlock the previous locked file.
*
* @param lockObj
* the object get from the lock.
*/
public void unlock( Object lockObj )
{
if ( lockObj instanceof Lock )
{
Lock lock = (Lock) lockObj;
FileLock fLock = lock.lock;
FileChannel channel = fLock.channel( );
try
{
fLock.release( );
}
catch ( Exception ex )
{
log.log( Level.FINE, "exception occus while release the lock",
ex );
}
// after unlock the file, notify the waiting threads
synchronized ( channel )
{
channel.notify( );
}
releaseChannel( lock.name );
}
}
@Override
protected synchronized void write(final byte[] bytes, final int offset, final int length,
final boolean immediateFlush) {
if (isLocking) {
try {
@SuppressWarnings("resource")
final FileChannel channel = ((FileOutputStream) getOutputStream()).getChannel();
/*
* Lock the whole file. This could be optimized to only lock from the current file position. Note that
* locking may be advisory on some systems and mandatory on others, so locking just from the current
* position would allow reading on systems where locking is mandatory. Also, Java 6 will throw an
* exception if the region of the file is already locked by another FileChannel in the same JVM.
* Hopefully, that will be avoided since every file should have a single file manager - unless two
* different files strings are configured that somehow map to the same file.
*/
try (final FileLock lock = channel.lock(0, Long.MAX_VALUE, false)) {
super.write(bytes, offset, length, immediateFlush);
}
} catch (final IOException ex) {
throw new AppenderLoggingException("Unable to obtain lock on " + getName(), ex);
}
} else {
super.write(bytes, offset, length, immediateFlush);
}
}
/**
* ファイルがロックされているかを確認します
*
* @param path ファイル
* @return ロックされている場合true
*/
public static boolean isLocked(Path path) {
if (!Files.isRegularFile(path)) {
return false;
}
try (FileChannel fc = FileChannel.open(path,
StandardOpenOption.CREATE, StandardOpenOption.WRITE)) {
FileLock lock = fc.tryLock();
if (lock != null) {
lock.release();
return false;
} else {
return true;
}
} catch (IOException e) {
return true;
}
}
private void removeInvalidLock(File lockDir) {
try {
boolean revokeLock = false;
File lockedFile = new File(lockDir, LOCK_FILE_NAME);
try (RandomAccessFile raf = new RandomAccessFile(lockedFile, "rw")) {
FileLock fileLock = raf.getChannel().tryLock();
if (fileLock != null) {
logger.warn("Removing invalid lock {}", getLockedBy());
fileLock.release();
revokeLock = true;
}
} catch (OverlappingFileLockException exc) {
// lock is still valid
}
if (revokeLock) {
revokeLock();
}
} catch (IOException e) {
logger.warn(e.toString(), e);
}
}
public static void lockProcess(String lockFileName) {
if (!CommonUtil.isEmptyString(lockFileName)) {
// https://stackoverflow.com/questions/7036108/prevent-launching-multiple-instances-of-a-java-application
File file = new File(lockFileName);
try {
FileChannel fc = FileChannel.open(file.toPath(),
StandardOpenOption.CREATE,
StandardOpenOption.WRITE);
FileLock lock = fc.tryLock();
if (lock == null) {
throw new RuntimeException("another instance is running");
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
/**
* Lock storage to provide exclusive access.
*
* <p> Locking is not supported by all file systems.
* E.g., NFS does not consistently support exclusive locks.
*
* <p> If locking is supported we guarantee exclusive access to the
* storage directory. Otherwise, no guarantee is given.
*
* @throws IOException if locking fails
*/
public void lock() throws IOException {
final File lockF = new File(root, STORAGE_FILE_LOCK);
final FileLock newLock = FileUtils.attempt(() -> tryLock(lockF), () -> "tryLock " + lockF);
if (newLock == null) {
String msg = "Cannot lock storage " + this.root
+ ". The directory is already locked";
LOG.info(msg);
throw new IOException(msg);
}
// Don't overwrite lock until success - this way if we accidentally
// call lock twice, the internal state won't be cleared by the second
// (failed) lock attempt
lock = newLock;
}
private void openMutable() throws IOException {
if (!this.file.exists()) {
_log.info("creating new checkpoint file {}", this.file);
}
try (RandomAccessFile raf = new RandomAccessFile(file, "rw")) {
this.ch = raf.getChannel();
for (UberTimer timer = new UberTimer(60 * 1000); !timer.isExpired();) {
FileLock lock = this.ch.tryLock();
if (lock != null) {
this.buf = this.ch.map(MapMode.READ_WRITE, 0, 512);
this.addr = UberUtil.getAddress(buf);
if (getServerId() == 0) {
Unsafe.putLong(this.addr + OFFSET_SERVER_ID, System.nanoTime());
}
return;
}
try {
Thread.sleep(1000);
}
catch (InterruptedException ignored) {
}
}
}
finally {
if (this.ch != null) {
this.ch.close();
}
}
throw new IOException("unable to acquire lock on " + file.getAbsolutePath());
}
synchronized boolean isFree()
{
if (_lock != null) {
return false;
}
if (! Files.isReadable(_path)) {
return true;
}
try (FileOutputStream fOs = (FileOutputStream) Files.newOutputStream(_path)) {
FileLock lock = fOs.getChannel().tryLock();
if (lock != null) {
lock.close();
return true;
}
else {
return false;
}
} catch (Exception e) {
log.finer(_path + ": isFree " + e);
log.log(Level.FINEST, e.toString(), e);
return true;
}
}
/**
* unlock odex file
**/
public void unLock(File bundleDexFile) {
File lockFile = new File(bundleDexFile.getParentFile().getAbsolutePath().concat("/lock"));
if (!lockFile.exists()) {
return;
}
if (lockFile == null || this.mRefCountMap.containsKey(lockFile.getAbsolutePath())) {
FileLockCount fileLockCount = this.mRefCountMap.get(lockFile.getAbsolutePath());
if (fileLockCount != null) {
FileLock fileLock = fileLockCount.mFileLock;
RandomAccessFile randomAccessFile = fileLockCount.fOs;
FileChannel fileChannel = fileLockCount.fChannel;
try {
if (RefCntDec(lockFile.getAbsolutePath()) <= 0) {
if (fileLock != null && fileLock.isValid()) {
fileLock.release();
}
if (randomAccessFile != null) {
randomAccessFile.close();
}
if (fileChannel != null) {
fileChannel.close();
}
}
} catch (IOException e) {
log.error(processName + " FileLock " + bundleDexFile.getParentFile().getAbsolutePath().concat("/lock") + " unlock FAIL! " + e.getMessage());
}
}
}
}
public void run() {
logger.fine("Checking for old temporary files...");
try {
// Find all temporary files with the mask mzmine*.scans
File tempDir = new File(System.getProperty("java.io.tmpdir"));
File remainingTmpFiles[] = tempDir.listFiles(new FilenameFilter() {
public boolean accept(File dir, String name) {
return name.matches("mzmine.*\\.scans");
}
});
if (remainingTmpFiles != null)
for (File remainingTmpFile : remainingTmpFiles) {
// Skip files created by someone else
if (!remainingTmpFile.canWrite())
continue;
// Try to obtain a lock on the file
RandomAccessFile rac = new RandomAccessFile(remainingTmpFile, "rw");
FileLock lock = rac.getChannel().tryLock();
rac.close();
if (lock != null) {
// We locked the file, which means nobody is using it
// anymore and it can be removed
logger.finest("Removing unused temporary file " + remainingTmpFile);
remainingTmpFile.delete();
}
}
} catch (IOException e) {
logger.log(Level.WARNING, "Error while checking for old temporary files", e);
}
}
public List<FileLock> removeAll() {
synchronized(lockList) {
List<FileLock> result = new ArrayList<FileLock>(lockList);
lockList.clear();
return result;
}
}
public List<FileLock> removeAll() {
synchronized(lockList) {
List<FileLock> result = new ArrayList<FileLock>(lockList);
lockList.clear();
return result;
}
}
@Override
@SuppressWarnings("try")
public void close() throws IOException {
try (
Owner<Channel, IOException> channelOwner = own(channel, IOException.class);
Owner<FileLock, IOException> fileLockOwner = own(fileLock, IOException.class);
) {
// Do nothing - the Java try-with-resources will correctly close both objects.
}
}
protected void implCloseChannel() throws IOException {
// Release and invalidate any locks that we still hold
if (fileLockTable != null) {
for (FileLock fl: fileLockTable.removeAll()) {
synchronized (fl) {
if (fl.isValid()) {
nd.release(fd, fl.position(), fl.size());
((FileLockImpl)fl).invalidate();
}
}
}
}
// signal any threads blocked on this channel
threads.signalAndWait();
if (parent != null) {
// Close the fd via the parent stream's close method. The parent
// will reinvoke our close method, which is defined in the
// superclass AbstractInterruptibleChannel, but the isOpen logic in
// that method will prevent this method from being reinvoked.
//
((java.io.Closeable)parent).close();
} else {
nd.close(fd);
}
}
@Override
public <A> void lock(
long position,
long size,
boolean shared,
@NullableDecl A attachment,
CompletionHandler<FileLock, ? super A> handler) {
checkNotNull(handler);
addCallback(lock(position, size, shared), handler, attachment);
}
protected void doStore(Context context, byte[] data, File file) {
if (file == null) {
return;
}
// Save
try {
File lockfile = new File(file.getAbsolutePath() + ".lock");
if (!lockfile.exists()) {
lockfile.createNewFile();
}
try (RandomAccessFile raf = new RandomAccessFile(lockfile, "rw");
FileChannel channel = raf.getChannel()) {
FileLock lock = channel.tryLock();
if (lock == null) {
throw new IOException("Can not lock the registry cache file " + file.getAbsolutePath() + ", ignore and retry later, maybe multi java process use the file");
}
try {
if (!file.exists()) {
file.createNewFile();
}
try (FileOutputStream outputFile = new FileOutputStream(file)) {
outputFile.write(data);
}
} finally {
lock.release();
}
}
} catch (Throwable e) {
logger.error("Failed to save model cache file, will retry, cause: " + e.getMessage(), e);
}
}
/**
* Lock storage to provide exclusive access.
*
* <p> Locking is not supported by all file systems.
* E.g., NFS does not consistently support exclusive locks.
*
* <p> If locking is supported we guarantee exclusive access to the
* storage directory. Otherwise, no guarantee is given.
*
* @throws IOException if locking fails
*/
public void lock() throws IOException {
FileLock newLock = tryLock();
if (newLock == null) {
String msg = "Cannot lock storage " + this.root
+ ". The directory is already locked";
LOG.info(msg);
throw new IOException(msg);
}
// Don't overwrite lock until success - this way if we accidentally
// call lock twice, the internal state won't be cleared by the second
// (failed) lock attempt
lock = newLock;
}
private synchronized void syncWrite(ByteBuffer buf) throws IOException {
FileLock lock = fileChannel.lock();
try {
fileChannel.write(buf);
} finally {
lock.release();
}
}
void closeLockFile() {
FileLock myfl = this.fl;
if (myfl != null) {
try {
FileChannel fc = myfl.channel();
if (myfl.isValid()) {
myfl.release();
}
fc.close();
} catch (IOException ignore) {
}
this.fl = null;
}
File f = this.lockFile;
if (f != null) {
if (f.delete()) {
if (logger.fineEnabled()) {
logger.fine("Deleted lock file " + f);
}
} else if (f.exists()) {
if (logger.fineEnabled()) {
logger.fine("Could not delete lock file " + f);
}
}
}
logger.info(LocalizedStrings.DEBUG, "Unlocked disk store " + name); // added
// to
// help
// debug
// 41734
}
public List<FileLock> removeAll() {
synchronized(lockList) {
List<FileLock> result = new ArrayList<FileLock>(lockList);
lockList.clear();
return result;
}
}
/**
* Trying to get a shared lock on a write-only FileChannel won't work.
*/
static void getReadLockFromOutputStream() throws IOException {
Path path = Files.createTempFile("foo", "txt");
try (FileOutputStream fis = new FileOutputStream(path.toFile());
FileLock lock = fis.getChannel()
.lock(0, Long.MAX_VALUE, true)) {
LOG.debug("This won't happen");
} catch (NonReadableChannelException e) {
LOG.error("The channel obtained through a FileOutputStream isn't readable. " + "You can't obtain an shared lock on it!");
throw e;
}
}
@Override
public FileLock tryLock(long position, long size, boolean shared) throws IOException {
checkLockArguments(position, size, shared);
// tryLock is not interruptible
return new FakeFileLock(this, position, size, shared);
}
private long append(FlatBufferBuilder h, FlatBufferBuilder c) throws IOException {
ByteBuffer bb1 = h.dataBuffer();
ByteBuffer bb2 = (c == null ? null : c.dataBuffer());
try (RandomAccessFile f = new RandomAccessFile(file, "rw"); FileChannel fc = f.getChannel(); FileLock lock = fc.lock()) {
//TODO can we make this more efficient - use a single byte buffer?
//Seek to end for append
f.seek(f.length());
long startPos = f.getFilePointer();
//Write header - length of SystemInfo header, length of content header
ByteBuffer header = ByteBuffer.allocate(8); //8 bytes = 2x 4 byte integers
int l1 = bb1.remaining();
int l2 = bb2 == null ? 0 : bb2.remaining();
header.putInt(l1);
header.putInt(l2);
header.flip();
//System.out.println("Lengths - header, content: " + l1 + ", " + l2);
int w1 = fc.write(header);
int w2 = fc.write(bb1);
int w3 = bb2 == null ? 0 : fc.write(bb2);
long total = w1 + w2 + w3;
//System.out.println("Wrote " + total + " bytes starting at position " + startPos);
//System.out.println("Post writing file length: " + file.length());
return total;
}
}