Java Filelock para leitura e escrita
-
20-09-2019 - |
Pergunta
Eu tenho um processo que será chamado com bastante frequência de Cron para ler um arquivo que possui certos comandos relacionados a mover. Meu processo precisa ler e gravar neste arquivo de dados - e mantê -lo bloqueado para impedir que outros processos o tocem durante esse período. Um processo completamente separado pode ser executado por um usuário em (potencial) gravar/anexar a esse mesmo arquivo de dados. Quero que esses dois processos joguem bem e acessem o arquivo apenas um de cada vez.
O Nio Filelock parecia ser o que eu precisava (sem escrever meus próprios arquivos do tipo semáforo), mas estou tendo problemas para travá -lo para ler. Eu posso travar e escrever muito bem, mas ao tentar criar bloqueio ao ler, recebo uma não -WritableChannException. É possível bloquear um arquivo para leitura? Parece que um RandomAccessFile está mais próximo do que eu preciso, mas não vejo como implementar isso.
Aqui está o código que falha:
FileInputStream fin = new FileInputStream(f);
FileLock fl = fin.getChannel().tryLock();
if(fl != null)
{
System.out.println("Locked File");
BufferedReader in = new BufferedReader(new InputStreamReader(fin));
System.out.println(in.readLine());
...
A exceção é lançada na linha do filelock.
java.nio.channels.NonWritableChannelException
at sun.nio.ch.FileChannelImpl.tryLock(Unknown Source)
at java.nio.channels.FileChannel.tryLock(Unknown Source)
at Mover.run(Mover.java:74)
at java.lang.Thread.run(Unknown Source)
Olhando para os javadocs, diz
Exceção desmarcada jogada quando uma tentativa é feita para escrever para um canal que não foi aberto originalmente para escrever.
Mas eu não preciso necessariamente escrever para isso. Quando tento criar um FileOutpustream, etc. Para escrever fins, é feliz até que eu tente abrir um FileInputStream no mesmo arquivo.
Solução
(a) Você está ciente de que o bloqueio do arquivo não impedirá que outros processos o tocem, a menos que eles também usem bloqueios?
(b) Você precisa travar através de um canal gravável. Pegue a fechadura por meio de um RandomAccessFile
no modo "RW" e depois abra seu FileInputStream
. Certifique -se de fechar os dois!
Outras dicas
Seria melhor se você criasse o bloqueio usando tryLock(0L, Long.MAX_VALUE, true)
.
Isso cria uma trava compartilhada, que é a coisa certa a fazer para ler.
tryLock()
é uma abreviação para tryLock(0L, Long.MAX_VALUE, false)
, ou seja, solicita um bloqueio exclusivo.