如果检测到互斥则停止当前线程

Stop current thread if mutual exclusion detected

在我的 android 应用程序中,我的一个模型 类 中有一个特定方法,并且此方法总是从 UI 线程以外的单独线程调用。

AlarmManger 定期使用此方法 运行 并且用户可以选择 运行 此方法来自 UI。 (AlarmManger 操作和 UI 操作从主应用程序 UI 线程以外的单独线程调用此方法)。

我只是不想让 运行 同时从 UI 和 AlarmManger 使用此方法。

我当然可以Synchronise这个方法,保证一个线程同时执行一个方法。但那是 NOT 我想要的。

我想抛出异常并停止第二个线程(可能是 UI 调用或 AlarmManager,视情况而定)(如果第二个线程已经在执行该方法)。所以我可以通知用户操作已取消,因为找到了另一个 运行ning 实例(AlarmManger 或表单 UI)。

请问遇到这种情况最好的方法是什么。谢谢

你为什么不使用信号量?您甚至可以使用 Java one

我根据你的问题做出以下假设:

  1. 你想保证方法的互斥,但如果有争用只是return(表示方法没有执行),而不是阻塞线程。
  2. 您需要模型的实例 class 可重用(例如,假设一旦一个线程退出该方法,其他线程可以再次调用)

为此,最简单的选择可能是 ReentrantLock::tryLock。类似这样的东西(代码未编译或测试。)

class MyClass {
    private final ReentrantLock lock = new ReentrantLock();
    public void theMethod() {
        if(!lock.tryLock()) {
            throw new IllegalStateException("Running already");
        }
        try {
            // do stuff
        } finally {
            lock.unlock(); 
        }
    }
}

抛出异常以表明方法正在执行意味着通过异常执行流程控制,这不是好的做法。除非你有充分的理由保留例外,否则我建议改为:

class MyClass {
    private final ReentrantLock lock = new ReentrantLock();
    public boolean theMethod() {
        if(!lock.tryLock()) {
            return false;
        }
        try {
            doStuff();
        } finally {
            lock.unlock(); 
        }
        return true;
    }
}

return 值表明该方法是否可以 运行,因此调用者可以做出相应的反应。

如果上面的 (2) 不适用(也就是说,您只想 运行 该方法一次并确保它永远不会再次执行),那么您可以简单地这样做:

class MyClass {
    private final AtomicBoolean hasExecuted = new AtomicBoolean(false);
    public boolean theMethod() {
        if(!hasExecuted.compareAndSet(false, true) {
            return false; // or throw an exception
        }
        doStuff();
        return true;
    }
}

希望对您有所帮助。