我想阻止来自更多3个线程的方法执行。该方法可以递归地执行。我有以下agly代码。我可以通过更好的方式实现这个目标吗?
private static class MyHolder {
private static Semaphore limitThreadsSemaphore = new Semaphore(3);
private static Set<Thread> asquiredThreads = new HashSet<Thread>();
}
@Override
public void someMethod() {
if (!MyHolder.asquiredThreads.contains(Thread.currentThread())) {
synchronized (MyHolder.asquiredThreads) {
if (!MyHolder.asquiredThreads.contains(Thread.currentThread())) {
try {
MyHolder.limitThreadsSemaphore.acquire();
MyHolder.asquiredThreads.add(Thread.currentThread());
} finally {
MyHolder.limitThreadsSemaphore.release();
MyHolder.asquiredThreads.remove(Thread.currentThread());
}
}
}
}
return super.someMethod();
}
感谢。
答案 0 :(得分:0)
我想&#34; someMethod&#34;是你要阻止执行的方法,是吗?你为什么不这样做? :
private static class MyHolder {
private static Semaphore limitThreadsSemaphore = new Semaphore(3);
public boolean semaphoreAdquired = false; //Make it private
public Semaphore getSemaphore()
{
return limitThreadsSemaphore;
}
}
@Override
public void someMethod() {
boolean ReleaseSemaphore = false;
if(!semaphoreAdquired)
{
MyHolder.getSemaphore().acquire();
semaphoreAdquired = true;
ReleaseSemaphore = true;
}
super.someMethod();
if(ReleaseSemaphore)
{
MyHolder.getSemaphore().release();
semaphoreAdquired = false;
}
}
答案 1 :(得分:0)
根据Semaphor的文档,这应该只能在关键部分使用 acquire()
和release()
来实现。此外,您应该能够将信号量放在当前类中,不需要单独的类来包含Semaphor。
private static Semaphore limitThreadsSemaphore = new Semaphore(3);
@Override
public void someMethod() {
limitThreadsSemaphore.acquire();
// do work.
limitThreadsSemaphore.release();
}
更新:如果需要在线程内递归调用方法,那么最简单的方法是使用辅助方法获取信号,然后从该辅助方法调用递归方法获得sempahor。在所有初始调用中,您将调用助手而不是原始方法。
private static Semaphore limitThreadsSemaphore = new Semaphore(3);
public void someMethodHelper() {
limitThreadsSemaphore.acquire();
someMethod();
limitThreadsSemaphore.release();
}
@Override
public void someMethod() {
// do work, with recursive calls.
}
答案 2 :(得分:0)
最简单的方法是将递归方法重构为私有,然后让公共方法无条件地获取信号量,调用私有方法然后再次释放信号量。递归调用直接路由到私有方法,因此不要通过信号量保护代码。
如果那不是一个选项,那么我能想到的最简单的方法就是使用ThreadLocal标志
ThreadLocal<Object> alreadyIn = new ThreadLocal<>();
public void someMethod() {
boolean needSem = (alreadyIn.get() == null);
if(needSem) {
semaphore.acquire();
alreadyIn.set(new Object());
}
try {
// do stuff
} finally {
if(needSem) {
alreadyIn.remove();
semaphore.release();
}
}
}