简体   繁体   English

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

[英]Stop current thread if mutual exclusion detected

In my android Application I've got a specific method in one of my MODEL classes and this method always gets called from a separate thread other than UI thread. 在我的android应用程序中,我的一个MODEL类中有一个特定的方法,并且总是从UI线程以外的单独线程中调用此方法。

The AlarmManger periodically runs this method and also user have the option to run this method from UI . AlarmManger定期运行此方法,用户也可以选择从UI运行此方法。 (AlarmManger operation and UI operation call this method from a separate thread other than Main application UI thread). (AlarmManger操作和UI操作从除主应用程序UI线程以外的单独线程中调用此方法)。

I just do NOT want to allow to run this method same time from UI and AlarmManger. 我只是不想允许同时从UI和AlarmManger运行此方法。

Of course I can Synchronise this method and that guarantees one thread execute method at ones. 当然,我可以同步该方法,并保证一个线程执行一个方法。 But that's NOT what I want. 但这不是我想要的。

I want to throw an exception and stop the second thread (could be UI call or AlarmManager depending on situation) if one already executing the method. 我想抛出一个异常并停止第二个线程(根据情况可能是UI调用或AlarmManager),如果一个线程已经在执行该方法。 So I can inform user that operation cancelled as another running instance (AlarmManger or form UI) was Found. 因此,我可以通知用户,由于找到了另一个正在运行的实例(AlarmManger或表单UI)而取消了操作。

Can I ask what the best approach for a situation like this. 请问这种情况下最好的方法是什么? Thanks 谢谢

I make the following assumptions from your question: 我根据您的问题做出以下假设:

  1. You want to guarantee mutual exclusion on the method, but if there is contention just return (signalling that the method didn't execute), not block the thread. 您想保证方法上的互斥,但是如果存在争用,只需返回(表示该方法未执行),而不阻塞线程。
  2. You need the instance of the model class reusable (eg assume that once a thread exits the method, some other thread could call again) 您需要模型类的实例可重用(例如,假设一旦某个线程退出该方法,则其他某个线程可能会再次调用)

For this the simplest option could be ReentrantLock::tryLock . 为此,最简单的选项可以是ReentrantLock :: tryLock Something like this (code is not compiled or tested.) 这样的事情(代码未经过编译或测试。)

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(); 
        }
    }
}

Throwing an exception to signal that the method is being executed means performing flow-control via exceptions, which is not good practise. 抛出异常以表明该方法正在执行意味着通过异常执行流控制,这不是一个好习惯。 Unless you have a good reason for keeping an exception, I'd recommend this instead: 除非您有保留异常的充分理由,否则我建议这样做:

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

The return value signals whether the method could run or not, so the caller can react accordingly. 返回值表明该方法是否可以运行,因此调用者可以做出相应的反应。

If (2) above doesn't apply (that is, you just want to run the method once and ensure that it never gets executed again), then you can simply do this: 如果上面的(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;
    }
}

I hope that helps. 希望对您有所帮助。

Why don't you use a semaphore? 为什么不使用信号灯? You can even use the Java one 您甚至可以使用Java

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

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