繁体   English   中英

如何定义必须调用的方法(属于我自己的类)

[英]How to define a method (of my own class) that must be invoked

我正在编写一个用于管理文件锁定的类FileLocker 多亏了java.nio.channels.FileLock,它的buildier方法锁定了一个文件(该目录作为方法的参数被接收) 。FileLocker类还包含release()方法,该方法释放在其buildier方法中创建的FileLock。 问题是,释放()方法必须被调用,否则该文件的锁定将永远不会被释放,其他进程将不允许使用这个文件(目前的JVM中)。 所以我的问题是:是否存在一种指示必须在所有使用FileLocker对象的代码中调用release()方法的方法,以便在这些代码编译期间,如果不使用release()方法会引发错误? (我在这里发布FileLocker类代码,只是为了展示其工作原理):

package essentialServer_Service;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.nio.channels.OverlappingFileLockException;
import essentialServer_Exception.EssentialServerException;

public class FileLocker implements ServerConfiguration{

String fileDirectory;
int filelockingAttempts;
int maxFilelockingAttempts;
FileChannel fileChannel;
RandomAccessFile randomAccessFile;
FileLock lock;
file f;

public FileLocker (String fileDirectory) throws EssentialServerException {

    this.fileDirectory = fileDirectory;
    filelockingAttempts = 0;
    maxFilelockingAttempts = maxDatabaseFilesLockingAttempts();
    f = new file(fileDirectory);
    f.make(); // To open a channel for a specific file, this file must exist
              // Note that the file.make() method throws an EssentialServerException if it seems to be impossible to create the file
    fileChannel = null;
    randomAccessFile = null;
    try{
        randomAccessFile = new RandomAccessFile(f, "rw");
        fileChannel = randomAccessFile.getChannel();
    }catch (FileNotFoundException e){
        throw new EssentialServerException(4);
    }
    lock = null;
    while (true) {
        try{
            lock = fileChannel.tryLock();
        }catch (OverlappingFileLockException e){
            filelockingAttempts++;
            if (filelockingAttempts > maxFilelockingAttempts && maxFilelockingAttempts > -1){
                try{
                    fileChannel.close();
                    randomAccessFile.close();
                }catch (IOException ee){
                    throw new EssentialServerException(7);
                }
                throw new EssentialServerException(5);
            }
        }catch (IOException e) {
            filelockingAttempts++;
            if (filelockingAttempts > maxFilelockingAttempts && maxFilelockingAttempts > -1){
                try{
                    fileChannel.close();
                    randomAccessFile.close();
                }catch (IOException ee){
                    throw new EssentialServerException(8);
                }
                throw new EssentialServerException(6);
            }
        }
    }
}

public void release (int ExceptionType) throws EssentialServerException{
    //The int value ExceptionType indicate the EssentialServerException's type that the FileLocker class should throw if the file unlocking fails
    try{
        lock.release();
        fileChannel.close();
        randomAccessFile.close();
    }catch (IOException ee){
        throw new EssentialServerException(ExceptionType);
    }
}
}

要直接回答您的问题-我不知道直接执行此方法的方法。 但是,我想向您介绍AutoCloseable界面。 它允许您编写可在“ 尝试使用资源”代码块中使用的代码。

不知道(完全忽略)代码的所有细节,使用它看起来像这样:

try (FileLocker locker = new FileLocker(filename)) {
  // Use locker
}

(可选)您可以添加捕获并最终阻止。 但这是要保证的是,在退出try块之前,将更衣室被“关闭”。

另外,如果FileLocker只是一个任意对象,除了再次释放它之外,不会在try {}块内进一步使用它,则可以如下简化:

try (new FileLocker(filename)) {
  // Your code during FileLocker
}

为了FileLocker起作用,您的FileLocker将必须扩展AutoCloseable 实际上,如果您的FileLocker将抛出IOException ,那么您也可以考虑扩展Closeable 您将需要实现close方法,该方法基本上必须调用您的release方法。

在Java中,锁定文件非常简单。 FileChannel(Java Doc)提供了锁定文件所需的所有方法。 tryLock()(Java Doc)方法将尝试获取文件上的锁,而无需等待。 如果获取了锁,则返回FileLock(Java Doc)的实例,否则此方法返回null。

FileLock仅用于进程间锁定,javadoc读取:

“文件锁代表整个Java虚拟机保存。它们不适合控制同一虚拟机中的多个线程对文件的访问。” 要在Java线程(相同的JVM)之间锁定,您需要使用一些共享锁。 我建议在文件编写类中使用同步块(根据这些文章,它可能表现最佳):

另一种方法是使用ReentrantLock:

final ReentrantLock lock = new ReentrantLock();

public void write(...){
  try {
    lock.lock()
    // do the writing
  } finally {
    // forget this and you're screwed
    lock.unlock();
  }
}

这种情况使用锁来解决写入的交错,而不是并发访问。进一步的并发锁具有更多的功能,但是同步锁也可以完成任务。 阅读文件

但是,都必须强制关闭锁和可重入锁。因此, 使用资源的新尝试功能很方便 ,它实现了AutoCloseable接口,与新的try-with-resource语法一起使用是必需的。 因此您可以编写一个简单的包装器,例如:

    public class LockWrapper implements AutoCloseable
{
    private final Lock _lock;
    public LockWrapper(Lock l) {
       this._lock = l;
    }

    public void lock() {
        this._lock.lock();
    }

    public void close() {
        this._lock.unlock();
    }
}

现在您可以编写如下代码:

try (LockWrapper someLock = new LockWrapper(new ReentrantLock()))
{
    someLock.lock();
    // ...
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM