首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如果某些线程在Java中的“`methodA`”中,如何确保“`methodB`”被“阻塞”?

如果某些线程在Java中的“`methodA`”中,如何确保“`methodB`”被“阻塞”?
EN

Stack Overflow用户
提问于 2016-09-28 08:52:06
回答 5查看 289关注 0票数 7

Class clazzmethodA()methodB()两种方法。

如果某些线程在Java中的methodB中(我使用的是Java8),如何确保methodA被“阻塞”?

所谓“阻塞methodB",我的意思是”等待到methodA()中没有线程“。(感谢@AndyTurner)

请注意,上面的要求允许以下情况:

  1. 多个线程同时在methodA中。
  2. 多个线程在methodB中,而没有线程在methodA中。
  3. methodB中的线程不会阻止其他线程进入methodA

我的试验:我使用StampedLock lock = new StampedLock

  • methodA中,调用long stamp = lock.readLock()
  • 创建一个新方法unlockB并在其中调用lock.unlockRead(stamp)
  • methodB中,打电话给long stamp = lock.writeLock()lock.unlockWrite(stamp)

但是,这种锁定策略不允许出现上述第二种和第三种情况。

编辑:我意识到我没有明确规定methodAmethodB之间同步的要求。@JaroslawPawlak给出的方法适用于当前的需求(我接受它),但不是出于我的初衷(也许我应该首先澄清它,然后将它放在另一个线程中)。

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2016-09-28 09:27:30

我认为这能起作用:

代码语言:javascript
复制
private final Lock lock = new ReentrantLock();
private final Semaphore semaphore = new Semaphore(1);
private int threadsInA = 0;

public void methodA() {
    lock.lock();
    threadsInA++;
    semaphore.tryAcquire();
    lock.unlock();

    // your code

    lock.lock();
    threadsInA--;
    if (threadsInA == 0) {
        semaphore.release();
    }
    lock.unlock();
}

public void methodB() throws InterruptedException {
    semaphore.acquire();
    semaphore.release();

    // your code
}

进入methodA的线程增加了计数,并试图从信号量中获取许可(也就是说,如果可用,它们将获得1个许可,但如果没有可用,则只会继续使用)。当最后一个线程离开methodA时,许可证将被返回。我们不能使用AtomicInteger,因为从信号量更改计数和获取/释放许可必须是原子的。

进入methodB的线程需要有一个许可(如果没有可用的话将等待许可),但是在获得许可之后,它们会立即返回它,允许其他线程进入methodB

编辑:

另一个更简单的版本:

代码语言:javascript
复制
private final int MAX_THREADS = 1_000;
private final Semaphore semaphore = new Semaphore(MAX_THREADS);

public void methodA() throws InterruptedException {
    semaphore.acquire();

    // your code

    semaphore.release();
}

public void methodB() throws InterruptedException {
    semaphore.acquire(MAX_THREADS);
    semaphore.release(MAX_THREADS);

    // your code
}

methodA中的每个线程都持有一个许可证,该许可在线程离开methodA时释放。

进入methodB的线程等待到所有1000个允许时才可用(即在methodA中没有线程),但不要持有它们,这允许其他线程在methodB仍在执行时输入这两个方法。

票数 4
EN

Stack Overflow用户

发布于 2016-09-28 09:01:53

为什么不使用一种外部协调器呢?我指的是另一个类,它将负责在允许时调用methodA或methodB。多线程仍然可以通过锁定或使用一些AtomicBoolean(s)来处理.

请在下面找到一份幼稚的草案,说明如何做到这一点。

代码语言:javascript
复制
public class MyOrchestrator {

@Autowired
private ClassWithMethods classWithMethods;

private AtomicBoolean aBoolean = = new AtomicBoolean(true);

 public Object callTheDesiredMethodIfPossible(Method method, Object... params) {
   if(aBoolean.compareAndSet(true, false)) {
      return method.invoke(classWithMethods, params);
      aBoolean.set(true);
   }
   if ("methodA".equals(method.getName())) {
      return method.invoke(classWithMethods, params);
   }
 } 

}
票数 0
EN

Stack Overflow用户

发布于 2016-09-28 09:16:39

您不能真正阻止调用methodA或methodB (其他线程在其他方法中),但是您可以以这样的方式实现线程间通信,这样您仍然可以实现您想要的结果。

代码语言:javascript
复制
class MutualEx {
   boolean lock = false;

   public synchronized void methodA() {
      if (lock) {
         try {
            wait();
         }catch (InterruptedException e) {

         }
      }
      //do some processing
      lock = true;
      notifyAll();
   }

   public synchronized void methodB() {
      if (!lock) {
         try {
            wait();
         }catch (InterruptedException e) {

         }
      }

       //do some processing
      lock = false;
      notifyAll();
   }
}

现在,要使其工作,您创建的任何线程对象都应该有一个对MutualEx对象的同一个实例的引用。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39742466

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档