package javacodebook.io.filelock; import java.io.*; import java.nio.*; import java.nio.channels.*; /** * Sperren einer Datei während der Schreib-/Leseoperationen. Dadurch kann * ein Datenaustausch mit anderen Programmen durchgeführt werden. Zum testen * kann dieses Programm zweimal aufgerufen werden, so dass 2 JVMs gestartet * werden. Dadurch wird ein konkurrierender Zugriff erzeugt. */ public class LockFileTest { //Die Methode versucht, die Datei zu sperren und eine neue Sequenznummer //zu erzeugen public static int newSequenceNum(FileChannel channel) { int seqNum = -1; ByteBuffer buffer = ByteBuffer.allocate(4); try { //Erstmal versuchen, die Datei exklusiv zu öffnen FileLock lock = channel.tryLock(); //wenn erfolgreich, dann Inhalt der Datei lesen, Zahl um 1 erhöhen //und wieder in die Datei schreiben if(lock != null) { channel.position(0); channel.read(buffer); buffer.rewind(); seqNum = buffer.getInt() + 1; buffer.clear(); //Erhöhten Zahlenwert in den Buffer schreiben und sofort zurückspulen buffer.putInt(seqNum).rewind(); channel.position(0); channel.write(buffer); //Sperrung der Datei aufheben lock.release(); } } catch(IOException e) { e.printStackTrace(System.out); } return seqNum; } public static void main(String[] args) throws Exception { if(args.length < 1) printUsage(); File syncFile = new File(args[0]); //Datei zum beliebigen Lesen und schreiben öffnen RandomAccessFile file = new RandomAccessFile(syncFile, "rw"); //Einen Channel öffnen FileChannel channel = file.getChannel(); //Mit der Zufallszahl soll der Prozess von einem parallel laufenden //anderen Java-Prozess unterschieden werden int myId = new java.util.Random().nextInt(100); //Ausgabe in Log-Datei schreiben zwecks Nachverfolgung File logFile = new File(syncFile.getParent() + File.separator + "channel" + myId + ".log"); PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(logFile))); //Zugriffe auf die Sequenzdatei starten for(int i = 0; i < 1000; i++) { int seqNum = newSequenceNum(channel); if(seqNum == -1) out.println("Sequenz blockiert"); else out.println("Aktuelle Sequenznummer für Kanal " + myId + ": " + seqNum); Thread.sleep(10); } //Channel und Dateien schliessen channel.close(); file.close(); out.close(); } private static void printUsage() { System.out.println("Aufruf: java javacodebook.io.filelock.LockFileTest Dateiname"); System.exit(0); } }