I have a java JAR file that is triggered by a SQL server job. It's been running successfully for months. The process pulls in a structured flat file to a staging database then pushes that data into an XML file.
However yesterday the process was triggered twice at the same time. I can tell from a log file that gets created, it looks like the process ran twice simultaneously. This caused a lot of issues and the XML file that it kicked out was malformed and contained duplicate nodes etc.
My question is, is this a known issue with Java JVM's spawning multiple instances of itself? Or should I be looking at sql server as the culprit? I'm looking into 'socket locking' or file locking to prevent multiple instances in the future.
This is the first instance of this issue that I've ever heard of.
More info:
The job is scheduled to run every minute. The job triggers a .bat file that contains the java.exe - jar filename.jar
The java program runs, scans a directory for a file and then executes a loop to process if the file if it finds one. After it processes the file it runs another loop that kicks out XML messages.
I can provide code sa开发者_JAVA技巧mples if that would help.
Thank you,
Kevin
It's not a Java problem. If you want the app to run alone, no copies, you should use the shell script or the java app to make and remove a lock somewhere.
You actually start multiple java's by starting more than 1 batch job with the same command. Windows nor Java can now that's not what you want. You could solve that by something like:
public static void main(String [ ] args)
{
createLockIfNotExists();
try {
yourstuff;
} finally {
releaseLock();
}
}
private static void createLockIfNotExists() throws MyLockAlreadyExists {
// A bit tricky
// check if LOCKFILE exists, if yes throw MyLockAlreadyExists
// try to create LOCKFILE, can fail if at 1 ms earlier an other app created
// that file, so an exception while creating also results in LockAlreadyExists
}
Are there good examples somewhere which handle this locking? Maybe in Apache Commons?
Here seems to be a functioning example for Windows.
You could also use the database to write your lock. Lock the locking table before you use it of course so no 2 processes write their lock at the same time, and afterwards read the lock record to check whether you actually got the lock. Something like pseudo code:
SELECT * FROM lock_table;
if locks.length > 0: someone else is running
LOCK lock_table;
INSERT INTO lock_table VALUES(my_pid);
UNLOCK lock_table;
SELECT pid FROM lock_table;
if pids.length > 1: what happened?
if pids[0] != my_pid: someone else got the lock
A bit more juice and you also add not only the PID but also a timestamp, and check whether that timestamp is stale (too old).
精彩评论