JAVA: — Общий доступ к файлам и блокировка между несколькими Java-приложениями, не работающими в Linux.

У меня есть два отдельных процесса Java. Скажите ABC и DEF. DEF является потомком ABC (то есть DEF порождается ABC. И ABC, и DEF порождаются с использованием двух jar-файлов ABc.jar и DEF.jar соответственно). Мое требование состоит в том, чтобы сохранить файл, общий как для ABC, так и для DEF. Этот файл создан ABC и будет заблокирован. DEF проверяет, разблокирован ли файл. Если разблокирован, процесс DEF завершается. Это связано с проблемой процесса-сироты, когда дочерний процесс не уничтожается при сбое родительского процесса.

Итак, в этом случае созданный ABC файл останется заблокированным до выхода ABC. DEF уже проверяет снята ли блокировка файла. Поскольку условием снятия блокировки является завершение ABC, DEF завершается, как только завершается ABC.

Итак, я создал класс FileLock.java в процессе ABC:

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileLock;

public class FileLock {

    public FileLockExample() throws FileNotFoundException {
        FileOutputStream fileOutStream;
        try {
            fileOutStream= new FileOutputStream("Temp.txt");
            FileLock fileLock ;
            try {
                fileLock = fileOutStream.getChannel().tryLock();
                if (fileLock != null) {
                    System.out.println("Locked File");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

        } catch (FileNotFoundException e) {

            e.printStackTrace();
        }

    }
}

Итак, файл Temp.txt создан и заблокирован.

Теперь я добавил функцию в DEF, где я проверяю, заблокирован ли файл.

public static void isFileUnlocked() {
        Integer count = 1000;
        boolean isFirstTry = false;
        while (count > 0) {
            try {
                if (!isFirstTry) {
                    FileOutputStream fos = new FileOutputStream("Temp.txt");
                    FileLock fileLock = fos.getChannel().tryLock();
                    isFirstTry = true;
                }
                FileInputStream fis = new FileInputStream("Temp.txt");
                fis.read();
                System.exit(0);
            } catch (IOException x) {

            }
          Thread.sleep(1000);
          count--;
        }
    }

Функция isFileUnlocked() в процессе DEF проверяет, снимается ли блокировка файла каждую секунду. Если блокировка снята, это означает, что ABC был прекращен по каким-то причинам. Таким образом, DEF завершает работу, как только снимается блокировка файла.

Я проверил это в Windows, и, похоже, это работает. Тем не менее, в Linux процесс DEF существует, как только вызывается функция isFileUnlocked(). Таким образом, когда DEF пытается прочитать файл, он может это сделать. (Что может означать, что файл разблокирован).

Любые мысли по этому поводу?


person Abhijith.M    schedule 14.07.2020    source источник
comment
Почему вы не проверяете блокировку в программе DEF?   -  person stdunbar    schedule 14.07.2020


Ответы (1)


Предполагая, что [заблокированный] файл не закрывается при вызове метода checkIfFileIsUnlocked(), а также предполагая, что вы вызываете метод checkIfFileIsUnlocked() с правильным параметром, чтобы проверить, заблокирован ли файл, вам нужно прочитать из файла. Простое открытие файла не вызовет исключение.

Это очень плохо написанный пример, но он просто предназначен для демонстрации того, как реализовать вашу проверку.


try {
    FileOutputStream fos = new FileOutputStream("lockfile.txt");
    FileLock fileLock = fos.getChannel().tryLock();

    FileInputStream fis = new FileInputStream("lockfile.txt");
    fis.read();
}
catch (IOException x) {
    x.printStackTrace();
}

Когда приведенный выше код выполняется, следующая строка вызывает исключение.

fis.read()

Исключение составляет:

java.io.IOException: The process cannot access the file because another process has locked a portion of the file

person Abra    schedule 14.07.2020
comment
Тот же код, который работал в Windows, не работает в Linux. В фрагменте, которым вы поделились, он никогда не входит в блок catch при работе в Linux. - person Abhijith.M; 15.07.2020
comment
@Abhijith.M Показывает ли Linux ту же проблему с NIO, заменяя первые 2 строки выше на FileChannel ch = FileChannel.open(p, StandardOpenOption.WRITE); FileLock fileLock = ch.tryLock(); - person DuncG; 16.07.2020
comment
@DuncG: Спасибо за предложение. Я пробовал так, как ты сказал. Это работало в Windows, но не в Linux. - person Abhijith.M; 16.07.2020
comment
@Abra: я изменил вопрос. Есть ли у вас какие-либо мысли о том, почему механизм блокировки файлов не работает должным образом в Linux? - person Abhijith.M; 16.07.2020