2015-01-23 2 views
2

Я пишу программу, которая записывает в один файл из разных потоков на одном JVM и из разных JVM-процессов. Есть ли способ заблокировать файл как для потоков, так и процессов, так что независимо от того, сколько потоков/процессов пытается писать одновременно, только 1 может писать за один раз?Блокировка файлов между потоками и процессами

В настоящее время у меня есть что-то похожее на следующее, которое работает для блокировки потоков, но не для блокировки процессов. Если я попытаюсь использовать FileLock поверх реализации ниже, появится synchronized.

import org.apache.commons.io.FileUtils; 
import org.apache.commons.io.IOUtils; 
import scripts.com.adz.commons.utils.FileUtilities; 

import java.io.*; 

public class Foo { 
    public static void main(String[] args) throws IOException { 
     Bar bar = new Bar(); 
     bar.start(); 

     while (true) { 
      FileUtilities.writeObjectToFile("C:\\test.html", "foo"); 
     } 
    } 
} 

class Bar extends Thread { 
    @Override 
    public void run() { 
     while (true) { 
      try { 
       FileUtilities.writeObjectToFile("C:\\test.html", "bar"); 
      } catch (IOException ignored) {} 
     } 
    } 
} 

class FileUtilitiess { 
    private static final Object _lock = new Object(); 

    public static <T> T readObjectFromFile(File file) throws IOException, ClassNotFoundException { 
     synchronized (_lock) { 
      final byte[] bytes = FileUtils.readFileToByteArray(file); 

      ByteArrayInputStream bis = null; 
      ObjectInputStream ois = null; 

      try { 
       ois = new ObjectInputStream(bis = new ByteArrayInputStream(bytes)); 

       return (T) ois.readObject(); 
      } finally { 
       IOUtils.closeQuietly(ois); 
       IOUtils.closeQuietly(bis); 
      } 
     } 
    } 

    public static void writeObjectToFile(File file, Object object) throws IOException { 
     System.out.println("Sent object: " + object.toString()); 
     synchronized (_lock) { 
      System.out.println("Writing object: " + object.toString()); 

      ByteArrayOutputStream bos = null; 
      ObjectOutputStream oos = null; 

      try { 
       oos = new ObjectOutputStream(bos = new ByteArrayOutputStream()); 
       oos.writeObject(object); 

       FileUtils.writeByteArrayToFile(file, bos.toByteArray()); 

       // - Start: For testing lock. 
       try { 
        Thread.sleep(10000); 
       } catch (InterruptedException ignored) {} 
       // - End: For testing lock. 
      } finally { 
       IOUtils.closeQuietly(oos); 
       IOUtils.closeQuietly(bos); 
      } 
     } 
    } 
} 
+0

Вы имеете в виду [FileLock] (http://docs.oracle.com/javase/7/docs/api/java/nio/channels/FileLock.html)? –

+0

FileLock не работает для нескольких потоков: «Они не подходят для управления доступом к файлу несколькими потоками на той же виртуальной машине». –

+1

Показать свой код с помощью 'FileLock' на месте; не должно быть причин, по которым они не могут сосуществовать. Однако я чувствую, что вы используете неправильное решение для любой проблемы, которую пытаетесь решить, и, вероятно, вы получите более качественные ответы, если будете описывать проблему, а не вашу реализацию. – kdgregory

ответ

3

См FileLockjavadoc:

файла блокировки удерживаются от имени всей виртуальной машины Java.

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

Чтобы заблокировать доступ к файлам из разных потоков, вы должны инкапсулировать код IO файла и выполнить синхронизированное выполнение.

Смежные вопросы