Java-如何知道当前是否正在运行特定方法

时间:2018-10-03 08:01:41

标签: java

我有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;
} 

在此代码中:

  • “方法”-此方法只有一个实例可以同时运行
  • “ monitorMethod”-用于监视的方法

这不是最佳解决方案:“ methodWrapper”中的“ finally”可能无法执行(在某些情况下,例如使用System.exit(0)),因此有时“ ifRunning”可以在最后保留为真方法。结果从那一刻起Application1就会认为该方法始终在运行。

那么我的目标是否有更好的解决方案?

4 个答案:

答案 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

相关问题