我有2个Web应用程序:Application1和Application2-都是REST应用程序。
Application1有时在Application2中调用方法。
这是非常重要的部分-此方法仅一个实例应同时运行。 因此,在从Application1调用Application2中的Application方法之前,将调用其他请求以测试方法当前是否正在运行。
现在我以这种方式实现它(这不是实际的代码-这只是为了大致展示实际的代码做什么):
static Boolean ifRunning = false;
static void methodWrapper() throws Exception {
try {
ifRunning = true;
method();
} finally {
ifRunning = false;
}
}
static void method() {
// do something
}
static Boolean monitorMethod() {
return ifRunning;
}
在此代码中:
这不是最佳解决方案:“ methodWrapper”中的“ finally”可能无法执行(在某些情况下,例如使用System.exit(0)),因此有时“ ifRunning”可以在最后保留为真方法。结果从那一刻起Application1就会认为该方法始终在运行。
那么我的目标是否有更好的解决方案?
答案 0 :(得分:4)
您的代码目前存在的问题是,如果从多个线程中调用该代码,它将无法正常工作:不能保证其他线程会看到running
的“正确”值。
您可以使用Semaphore
:
static final Semaphore running = new Semaphore(1);
static void methodWrapper() throws Exception {
if (!running.tryAcquire()) {
throw new Exception("Already running!!!");
}
try {
method();
} finally {
running.release();
}
}
Semaphore
的缺点是您无法查询它是否正在运行。相反,您可以使用AtomicBoolean
:
static final AtomicBoolean running = new AtomicBoolean();
static void methodWrapper() throws Exception {
if (!running.compareAndSet(false, true)) {
throw new Exception("Already running!!!");
}
try {
method();
} finally {
running.set(false);
}
}
现在您得到的行为与信号灯基本相同,但是您可以调用running.get()
来查看当时是否有任何方法在运行该方法。
答案 1 :(得分:0)
您不必担心System.exit
。之后,您的应用程序仍然会停止。那么,为什么要关心该方法是否以前运行过。
我认为,问题不是递归问题。因此您确实有问题,因为您的代码不是线程安全的!您必须同步对isRunning的每次访问,或者使其可变。我建议使用private volatile boolean
(原始布尔值!)。
答案 2 :(得分:0)
回调函数对于在System.exit(0)之前进行通知非常有用。
public class Tester {
public static void main(String[] args) {
method(() -> {
System.out.println("System.exit() will be called!");
});
System.out.println("System.exit() did not called!");
}
private static void method(Callback callback) {
if (Math.random() * 10 > 5) {
callback.notifySystemExit();
System.exit(0);
}
System.out.println("JVM is saved!");
}
}
@FunctionalInterface
interface Callback {
void notifySystemExit();
}
答案 3 :(得分:-1)
通常,您可以获取当前线程的堆栈跟踪,以获取当前执行的方法的详细信息。
Thread.currentThread().getStackTrace()
通常将包含当前正在执行的方法,但是存在陷阱。
请参阅Java文档:Stack Trace Java Docs