Class clazz有methodA()和methodB()两种方法。
如果某些线程在Java中的
methodB中(我使用的是Java8),如何确保methodA被“阻塞”?
所谓“阻塞methodB",我的意思是”等待到methodA()中没有线程“。(感谢@AndyTurner)
请注意,上面的要求允许以下情况:
methodA中。methodB中,而没有线程在methodA中。methodB中的线程不会阻止其他线程进入methodA。我的试验:我使用StampedLock lock = new StampedLock。
methodA中,调用long stamp = lock.readLock()unlockB并在其中调用lock.unlockRead(stamp)。methodB中,打电话给long stamp = lock.writeLock()和lock.unlockWrite(stamp)。但是,这种锁定策略不允许出现上述第二种和第三种情况。
编辑:我意识到我没有明确规定methodA和methodB之间同步的要求。@JaroslawPawlak给出的方法适用于当前的需求(我接受它),但不是出于我的初衷(也许我应该首先澄清它,然后将它放在另一个线程中)。
发布于 2016-09-28 09:27:30
我认为这能起作用:
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。
编辑:
另一个更简单的版本:
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仍在执行时输入这两个方法。
发布于 2016-09-28 09:01:53
为什么不使用一种外部协调器呢?我指的是另一个类,它将负责在允许时调用methodA或methodB。多线程仍然可以通过锁定或使用一些AtomicBoolean(s)来处理.
请在下面找到一份幼稚的草案,说明如何做到这一点。
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);
}
}
}发布于 2016-09-28 09:16:39
您不能真正阻止调用methodA或methodB (其他线程在其他方法中),但是您可以以这样的方式实现线程间通信,这样您仍然可以实现您想要的结果。
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对象的同一个实例的引用。
https://stackoverflow.com/questions/39742466
复制相似问题