Lock.java Source code

Java tutorial

Introduction

Here is the source code for Lock.java

Source

/*
 * Copyright (c) 2004 David Flanagan.  All rights reserved.
 * This code is from the book Java Examples in a Nutshell, 3nd Edition.
 * It is provided AS-IS, WITHOUT ANY WARRANTY either expressed or implied.
 * You may study, use, and modify it for any non-commercial purpose,
 * including teaching and use in open-source projects.
 * You may distribute it non-commercially as long as you retain this notice.
 * For a commercial use license, or to purchase the book, 
 * please visit http://www.davidflanagan.com/javaexamples3.
 */
//package je3.nio;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;

/**
 * Lock.java: this class demonstrates file locking and simple file read and
 * write operations using java.nio.channels.FileChannel. It uses file locking to
 * prevent two instances of the program from running at the same time.
 */
public class Lock {
    public static void main(String args[]) throws IOException, InterruptedException {
        RandomAccessFile file = null; // The file we'll lock
        FileChannel f = null; // The channel to the file
        FileLock lock = null; // The lock object we hold

        try { // The finally clause closes the channel and releases the lock
            // We use a temporary file as the lock file.
            String tmpdir = System.getProperty("java.io.tmpdir");
            String filename = Lock.class.getName() + ".lock";
            File lockfile = new File(tmpdir, filename);

            // Create a FileChannel that can read and write that file.
            // Note that we rely on the java.io package to open the file,
            // in read/write mode, and then just get a channel from it.
            // This will create the file if it doesn't exit. We'll arrange
            // for it to be deleted below, if we succeed in locking it.
            file = new RandomAccessFile(lockfile, "rw");
            f = file.getChannel();

            // Try to get an exclusive lock on the file.
            // This method will return a lock or null, but will not block.
            // See also FileChannel.lock() for a blocking variant.
            lock = f.tryLock();

            if (lock != null) {
                // We obtained the lock, so arrange to delete the file when
                // we're done, and then write the approximate time at which
                // we'll relinquish the lock into the file.
                lockfile.deleteOnExit(); // Just a temporary file

                // First, we need a buffer to hold the timestamp
                ByteBuffer bytes = ByteBuffer.allocate(8); // a long is 8 bytes

                // Put the time in the buffer and flip to prepare for writing
                // Note that many Buffer methods can be "chained" like this.
                bytes.putLong(System.currentTimeMillis() + 10000).flip();

                f.write(bytes); // Write the buffer contents to the channel
                f.force(false); // Force them out to the disk
            } else {
                // We didn't get the lock, which means another instance is
                // running. First, let the user know this.
                System.out.println("Another instance is already running");

                // Next, we attempt to read the file to figure out how much
                // longer the other instance will be running. Since we don't
                // have a lock, the read may fail or return inconsistent data.
                try {
                    ByteBuffer bytes = ByteBuffer.allocate(8);
                    f.read(bytes); // Read 8 bytes from the file
                    bytes.flip(); // Flip buffer before extracting bytes
                    long exittime = bytes.getLong(); // Read bytes as a long
                    // Figure out how long that time is from now and round
                    // it to the nearest second.
                    long secs = (exittime - System.currentTimeMillis() + 500) / 1000;
                    // And tell the user about it.
                    System.out.println("Try again in about " + secs + " seconds");
                } catch (IOException e) {
                    // This probably means that locking is enforced by the OS
                    // and we were prevented from reading the file.
                }

                // This is an abnormal exit, so set an exit code.
                System.exit(1);
            }

            // Simulate a real application by sleeping for 10 seconds.
            System.out.println("Starting...");
            Thread.sleep(10000);
            System.out.println("Exiting.");
        } finally {
            // Always release the lock and close the file
            // Closing the RandomAccessFile also closes its FileChannel.
            if (lock != null && lock.isValid())
                lock.release();
            if (file != null)
                file.close();
        }
    }
}