繁体   English   中英

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

[英]Stop current thread if mutual exclusion detected

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

AlarmManger定期运行此方法,用户也可以选择从UI运行此方法。 (AlarmManger操作和UI操作从除主应用程序UI线程以外的单独线程中调用此方法)。

我只是不想允许同时从UI和AlarmManger运行此方法。

当然,我可以同步该方法,并保证一个线程执行一个方法。 但这不是我想要的。

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

请问这种情况下最好的方法是什么? 谢谢

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

  1. 您想保证方法上的互斥,但是如果存在争用,只需返回(表示该方法未执行),而不阻塞线程。
  2. 您需要模型类的实例可重用(例如,假设一旦某个线程退出该方法,则其他某个线程可能会再次调用)

为此,最简单的选项可以是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;
    }
}

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

如果上面的(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;
    }
}

希望对您有所帮助。

为什么不使用信号灯? 您甚至可以使用Java

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM