Java中的跨进程同步

Saa*_*aar 9 java windows multithreading

如何同步在Windows上运行的两个Java进程?

我正在寻找类似于Win32 Named Mutex对象的东西,它允许两个进程使用相同的锁定对象.

谢谢

Jav*_*a42 14

Java跨进程锁:

// Tester
try {
    if (crossProcessLockAcquire(SomeClassInYourApp.class, 3000)) {
       // Success - This process now has the lock. (Don't keep it too long.)
    }
    else {
       // Fail (Timeout) - Another process still had the lock after 3 seconds.
    }
} finally {
    crossProcessLockRelease(); // try/finally is very important.
}

// Acquire - Returns success ( true/false )
private static boolean crossProcessLockAcquire(final Class<?> c, final long waitMS) {
    if (fileLock == null && c != null && waitMS > 0) {
        try {
            long dropDeadTime = System.currentTimeMillis() + waitMS;
            File file = new File(lockTempDir, c.getName() + ".lock");
            RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw");
            FileChannel fileChannel = randomAccessFile.getChannel();
            while (System.currentTimeMillis() < dropDeadTime) {
                fileLock = fileChannel.tryLock();
                if (fileLock != null) {
                    break;
                }
                Thread.sleep(250); // 4 attempts/sec
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    return fileLock == null ? false : true;
}

// Release
private static void crossProcessLockRelease() {
    if (fileLock != null) {
        try {
            fileLock.release();
            fileLock = null;
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

// Some class vars and a failsafe lock release.
private static File lockTempDir = new File(System.getProperty("java.io.tmpdir") + File.separator + "locks");
private static FileLock fileLock = null;
static {
    Runtime.getRuntime().addShutdownHook(new Thread() {
        public void run(){
            crossProcessLockRelease();
        }
    });
}    
Run Code Online (Sandbox Code Playgroud)


bez*_*max 6

在 Java 中不可能做你想做的事情。不同的 Java 应用程序将使用不同的 JVM,将自己完全分离到不同的“黑盒”中。但是,您有 2 个选择:

  1. 使用套接字(或通道)。基本上,一个应用程序将打开侦听套接字并开始等待,直到它收到一些信号。另一个应用程序将连接到那里,并在完成某事后发送信号。我会说这是在 99.9% 的应用程序中使用的首选方式。
  2. 您可以从 Java 调用 winapi。我不记得具体细节,但如果你用谷歌搜索“java winapi”,你可以找到大量的例子。


Ily*_*man 5

我简化了Java42的答案

用法

ProcessLock lock = new ProcessLock("lockKey");
lock.run(successLockRunnable, timeOutLockRunnable);
Run Code Online (Sandbox Code Playgroud)

使用此实现,successLockRunnable中的代码将锁定同一台计算机上的任何其他进程。

资源

/**
 * Created by Ilya Gazman on 13/06/2016.
 * Based on /sf/answers/670436721/
 */
public class ProcessLock {
    // Some class vars and a fail safe lock release.
    private File lockTempDir = new File(System.getProperty("java.io.tmpdir") + File.separator + "locks");
    private FileLock fileLock = null;
    private String key;

    public ProcessLock() {
        this("lock");
    }

    public ProcessLock(String key) {
        this.key = key;
        Runtime.getRuntime().addShutdownHook(new Thread() {
            public void run() {
                crossProcessLockRelease();
            }
        });
    }

    public void run(Runnable successCallback) {
        run(successCallback, null);
    }

    public void run(Runnable successCallback, Runnable timeOutCallback) {
        try {
            if (crossProcessLockAcquire(3000)) {
                successCallback.run();
            } else if (timeOutCallback != null) {
                timeOutCallback.run();
            }
        } finally {
            crossProcessLockRelease(); // try/finally is very important.
        }
    }

    // Acquire - Returns success ( true/false )
    private boolean crossProcessLockAcquire(final long waitMS) {
        if (fileLock == null && waitMS > 0) {
            try {
                long dropDeadTime = System.currentTimeMillis() + waitMS;
                File file = new File(lockTempDir, "_" + key + ".lock");
                RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw");
                FileChannel fileChannel = randomAccessFile.getChannel();
                while (System.currentTimeMillis() < dropDeadTime) {
                    fileLock = fileChannel.tryLock();
                    if (fileLock != null) {
                        break;
                    }
                    Thread.sleep(250); // 4 attempts/sec
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return fileLock != null;
    }

    // Release
    private void crossProcessLockRelease() {
        if (fileLock != null) {
            try {
                fileLock.release();
                fileLock = null;
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)