我有一个计划使用定时器独立运行的可运行JAR文件。如何限制独立执行并可通过Web应用程序执行的可运行JAR的执行。
相同的JAR通过web应用程序(在spring MVC中开发)执行。
如果jar通过计时器执行,那么当时不允许通过web应用程序执行,我必须限制JAR的执行。
注意:[我已经使用processbuilder来执行JAR。]
我有一个计划使用定时器独立运行的可运行JAR文件。如何限制独立执行并可通过Web应用程序执行的可运行JAR的执行。
相同的JAR通过web应用程序(在spring MVC中开发)执行。
如果jar通过计时器执行,那么当时不允许通过web应用程序执行,我必须限制JAR的执行。
注意:[我已经使用processbuilder来执行JAR。]
我想你正在开发可授权的jar。 在我看来,对于这种瓶子,最好是嵌入数据库,并保存Db中的执行时间和端口使用情况,并比较使用时间并对其进行限制。计时器的做法是不安全的,由于系统时间差异或防病毒资源或系统时间分配RE等。然而,对于监控器网络,你可以监视应用程序来处理这类问题,
public class Watchdog implements Runnable {
private Vector observers = new Vector(1);
private long timeout = -1;
private volatile boolean stopped = false;
public static final String ERROR_INVALID_TIMEOUT = "timeout less than 1.";
/**
* Constructor for Watchdog.
* @param timeout the timeout to use in milliseconds (must be >= 1).
*/
public Watchdog(long timeout) {
if (timeout < 1) {
throw new IllegalArgumentException(ERROR_INVALID_TIMEOUT);
}
this.timeout = timeout;
}
public void addTimeoutObserver(TimeoutObserver to) {
observers.addElement(to);
}
public void removeTimeoutObserver(TimeoutObserver to) {
//no need to synchronize, as Vector is always synchronized
observers.removeElement(to);
}
protected final void fireTimeoutOccured() {
Enumeration e = observers.elements();
while (e.hasMoreElements()) {
((TimeoutObserver) e.nextElement()).timeoutOccured(this);
}
}
/**
* Start the watch dog.
*/
public synchronized void start() {
stopped = false;
Thread t = new Thread(this, "WATCHDOG");
t.setDaemon(true);
t.start();
}
/**
* Stop the watch dog.
*/
public synchronized void stop() {
stopped = true;
notifyAll();
}
public synchronized void run() {
final long until = System.currentTimeMillis() + timeout;
long now;
while (!stopped && until > (now = System.currentTimeMillis())) {
try {
wait(until - now);
Boolean SafeToContinue=CheckDbCountDay();
if(SafeToContinue)
ExecJarUsingStrategyPattern(new StrategyDoIt());
else ExecJarUsingStrategyPattern(new showMessage());
} catch (InterruptedException e) {
callBack("plz call support");
}
}
if (!stopped) {
fireTimeoutOccured();
}
}
}
如果我理解正确你有不同的虚拟机执行相同的jar /代码(我将调用操作)。如果是这样,你可以设置一个锁定机制,独立于这些虚拟机。例如,您可以使用文件,但更好地使用数据库及其原生锁定功能:创建一个“锁定”(ID,版本,操作,到期)表,然后每次执行操作时尝试检索操作的锁定行,if行不存在或过期,则创建/更新锁定行设置过期并允许操作,否则抛出无法执行自锁定异常。如果操作崩溃,过期用于永远避免锁定,因为finally
无法执行(例如:OS崩溃)。为了避免双重/同时写入,您应该为锁定表使用DB optimistic locking功能,例如:版本字段。在操作结束时释放锁,删除该行。锁定行必须在不同的交易中创建和删除,与操作(如果有的话)分开创建和删除
实质上,您需要的是一个可以跨jvms工作的锁。或者,可以说,一种在jvms之间共享对象的方式,以便您可以锁定它们。这里有多种可用的解决方案,例如创建一个文件来指示一个锁,或者如果您的应用程序中已经有数据库,或者分发锁,则可以使用基于数据库的锁。 Terracotta是一个可能的解决方案。您也可以尝试apache zookeeper,而且来自apache的curator库使它非常易于使用。
动物园管理员和馆长:代码看起来简单:
lock = new InterProcessSemaphoreMutex(client, lockPath);
lock.acquire(5, TimeUnit.MINUTES);
// do something
lock.release();
完整的例子:这样做是使用数据库here
的最佳方式。 开始应用程序锁定一个特定的行(使用更新为了安全起见,以便两者都在同一时间启动)并在某处写入in_use。 然后你做生意,一旦完成更新同一行从in_use到完成。通过这种方式,在某个特定时间,您的jar的一个实例将执行您的业务代码。如果两者都在不同的计算机上,它也不会失败。
你可以检查是否存在的文件,以信号通知的.jar正在执行,如果是终止:
import java.io.File;
import java.io.IOException;
public class Main {
public static void main(String[] args) {
if (FileLock.exists()){
System.out.println("The file exists so the jar is running");
System.exit(0);
}
FileLock.createLockFile();
//start Running the .Jar File
/*
*
*
* CODE
*
*
*
*/
//Delete the file when the program terminates
FileLock.deleteLockFile();
System.out.println("Program exiting normally");
}
}
class FileLock {
private static File lock = new File("jar-running.txt");
public static boolean exists()
{
return lock.exists();
}
public static void createLockFile()
{
try {
lock.createNewFile();
} catch (IOException e) {
// the file already exists
System.exit(0);}
}
public static void deleteLockFile()
{
if(lock.exists()) lock.delete();
}
}
随着计时器你说的是操作系统特定的cron作业? – mika
@mika yes.it计划按时间间隔执行。 – bajrangi
最好的解决方案可能是让您的应用程序使用一个操作系统工具,该工具可以返回所有正在运行的进程的列表。如果您在列表中找到应用程序的名称,它已经在运行。您也可以使用信号量方法,例如在其中写入把你的应用程序的PID写入一个文件,然后(再次)使用操作系统工具来查找PID当前是否正在使用......但这可能更容易出错,实际上甚至有更多的编码需要执行。 Fyi,看看这里:http://stackoverflow.com/questions/2318220/how-to-detect-via-java-whether-a-particular-process-is-running-under-windows – mika