我有一个关键部分,我需要控制只有那些具有给定属性值的线程能够同时输入。
例如:我有处理产品的线程#1,线程#2处理产品,而线程#3处理服务
现在:
T1首先进入关键部分,以便处理产品
T2想要进入,但由于还有其他产品正在处理中,因此必须等待
T3是最后一个,它可以进入,因为它需要一个服务(不是产品)来处理
T1熄灭,现在T2可以进入
我觉得它看起来很简单,但我找不到符合要求的东西。 我的问题是,我怎样才能做到这一点?任何有关此信息来源的参考将不胜感激
非常感谢您提前
答案 0 :(得分:2)
我认为您无法锁定值类型但尝试此解决方法:将锁定对象放入数组并从ID访问该数组。
类似的东西:
private Object[] locks = new Object[] {new Object(), new Object()};
private void yourMethod(int id)
{
synchronized(locks[id]) //or id - 1 if you want to stick to your 1 and 2
{
//do your things
}
}
希望有所帮助
答案 1 :(得分:2)
这个怎么样:
private ConcurrentMap<Integer, Semaphore> semaphores = new ConcurrentHashMap<>();
public void enter(int id) {
Semaphore s = semaphores.computeIfAbsent(id, key -> new Semaphore(1));
try {
s.acquire();
// Critical section.
} catch (InterruptedException e) {
// Exception handling.
} finally {
s.release();
}
}
tryEnter(int)
来自Semaphore#tryAcquire()
。答案 2 :(得分:1)
我们以不同的方式对此问题进行了排序,并且使用普通锁定会产生高性能影响,而普通锁定在某些情况下会成为瓶颈。但我设法得到了一个解决方案,但未经过测试。这包含一个Lock类,它包含一个Locks池,并根据termId将它们提供给线程。共享相同termId的所有线程将提供相同的Lock。通过这种方式,我们可以获得按termId分组的所有线程,所有线程都排列在不同的队列中。我设置了一个固定的锁池,虽然我认为它也可以是动态的,可以根据需要删除和添加锁。
任何反馈都将不胜感激
import java.util.ArrayList;
import java.util.concurrent.Semaphore;
public class Lock {
private Lock() {}
private static class SingletonHolder {
/** ordered list. Locks with termId null must be at the end **/
public static final ArrayList<Lock> INSTANCES = new ArrayList<Lock>(){{
add(new Lock());
add(new Lock());
add(new Lock());
add(new Lock());
add(new Lock());
add(new Lock());
add(new Lock());
}};
public static synchronized Lock returnInstance(String termId){
ArrayList<Lock> sortedList = sortInstances();
for(Lock instance: sortedList){
if(termId.equals(instance.getTermId()))
return instance;
if(instance.getTermId()==null)
return instance;
}
return null;
}
public static ArrayList<Lock> sortInstances(){
ArrayList<Lock> sortedList=new ArrayList<Lock>();
for(Lock instance: INSTANCES){
if(instance.getTermId()==null)
sortedList.add(instance);
else
sortedList.add(0,instance);
}
return sortedList;
}
}
/**
* Use this method to get a reference to a singleton instance of
* {@link Lock}
*
* @return a singleton instance
*/
public static Lock getInstance(String termId) {
return SingletonHolder.returnInstance(termId);
}
private Semaphore lock = new Semaphore(1);
private String termId;
public void getLock(String termId) throws InterruptedException {
lock.acquire();
setTermId(termId);
}
public void releaseLock() {
lock.release();
setTermId(null);
}
public String getTermId() {
return termId;
}
public void setTermId(String termId) {
this.termId = termId;
}
}