我有一個計劃使用定時器獨立運行的可運行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