I provide two answers, one for Linux:
Don't run the program if it's already running, put this in a file called Main.java
import java.io.File;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
class JustOneLock {
FileLock lock;
FileChannel channel;
public boolean isAppActive() throws Exception{
File file = new File(System.getProperty("user.home"),
"FireZeMissiles1111" + ".tmp");
channel = new RandomAccessFile(file, "rw").getChannel();
lock = channel.tryLock();
if (lock == null) {
return true;
}
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
try {
lock.release();
channel.close();
} catch (Exception e) {
e.printStackTrace();
}
}
});
return false;
}
}
public class Main {
public static void main(String[] args)throws Exception {
JustOneLock u = new JustOneLock();
if (u.isAppActive()) {
System.out.println("Already active, stop!");
System.exit(1);
}
else {
System.out.println("NOT active... Do hard work for 5 seconds.");
try{Thread.sleep(5000);}catch(Exception e){}
}
}
}
Compile it and run it. Then open a new terminal and try to run it again while the other is running and it won't.
Another answer for Windows
This program will not allow itself to be run if it is already running on the current system. This is for windows only systems.
import java.io.*;
import java.util.prefs.Preferences;
public class JavaApplication3 {
public static void main(String[] args){
if(isRunning()){
System.out.println("Two instances of this program cannot " +
"be running at the same time. Exiting now");
}
else{
onStart();
epicHeavyWorkGoesHere();
onFinish();
}
}
public static void epicHeavyWorkGoesHere(){
try {
Thread.sleep(5000);
} catch (InterruptedException ex) {}
}
public static void onStart(){
Preferences prefs = Preferences.systemRoot().node("JavaApplication3");
prefs.put("RUNNINGPID", getCurrentPID());
}
public static void onFinish(){
Preferences prefs = Preferences.systemRoot().node("JavaApplication3");
prefs.put("RUNNINGPID", "");
}
public static boolean isRunning(){
Preferences prefs = Preferences.systemRoot().node("JavaApplication3");
if (prefs.get("RUNNINGPID", null) == null || prefs.get("RUNNINGPID", null).equals(""))
return false;
if (isProcessIdRunningOnWindows(Integer.parseInt(prefs.get("RUNNINGPID", null))))
return true;
return false;
}
public static String getCurrentPID(){
//This function is designed to get the PID from the windows system, it may
//not work for Linux or Mac. You'll have to acquire a suitable getCurrentPID function
try{
java.lang.management.RuntimeMXBean runtime = java.lang.management.ManagementFactory.getRuntimeMXBean();
java.lang.reflect.Field jvm = runtime.getClass().getDeclaredField("jvm");
jvm.setAccessible(true);
sun.management.VMManagement mgmt = (sun.management.VMManagement) jvm.get(runtime);
java.lang.reflect.Method pid_method = mgmt.getClass().getDeclaredMethod("getProcessId");
pid_method.setAccessible(true);
return pid_method.invoke(mgmt) + "";
}
catch(Exception e){
throw new RuntimeException("Cannot get the current PID");
}
}
public static boolean isProcessIdRunningOnWindows(int pid){
//This Function only works for windows, if you want it to work on linux
//you will have to go find a replacement method that takes the processID
//as a parameter and spits out a true/false if it is running on the system.
try {
Runtime runtime = Runtime.getRuntime();
String cmds[] = {"cmd", "/c", "tasklist /FI \"PID eq " + pid + "\""};
Process proc = runtime.exec(cmds);
InputStream inputstream = proc.getInputStream();
InputStreamReader inputstreamreader = new InputStreamReader(inputstream);
BufferedReader bufferedreader = new BufferedReader(inputstreamreader);
String line;
while ((line = bufferedreader.readLine()) != null) {
if (line.contains(" " + pid + " ")){
return true;
}
}
return false;
}
catch (Exception ex) {
throw new RuntimeException("Cannot run the tasklist command to query if a pid is running or not");
}
}
}
The strategy of the above code is to keep the PID around from the last run, if that PID is found running on the system, don't start. If you finish, reset.
The preferences are stored on Windows Registry in HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Prefs
I advise against using File Locking to make sure a java application doesn't run twice at the same time because if the program crashes or hangs forever and is killed, then the lock is left in an inconsistent state and perhaps may even survive a reboot which will cause problems because how will the program know the difference between a program which is still running and a program that has crashed and left the locked file locked?