我有一组资源,它们是Resource
类的实例。系统中的作业在运行时进入。每个作业都需要一组这些资源,并且必须独占使用它所需的所有资源才能继续。也就是说,为了使作业能够启动,它必须获取所需的所有资源的锁,并释放它一旦完成就获得的所有锁。因此,除非所需的所有资源都可用,否则作业无法开始处理。
在运行时之前不知道作业所需的资源。作业需要的资源列表作为Collection
ArrayList<Resource>
传递给它的构造函数。
这样做的一种方法是,在每个作业线程的run()
方法中,我可以同步“此”作业所需的所有资源的锁定。
synchronized (resource1) {
synchronized (resource2) {
...
}
}
但这是硬编码并且无法完成,因为作业所需的资源仅在运行时才知道。
我能想到的另一种方法是将资源放在一个集合结构中,这样当获取该集合的锁时,该集合中所有条目的锁也被获取,并且其他任何人都无法使用。
有Collections.synchronizedList()
。但是,它只锁定List
,而不是列表中的对象。
如何才能做到这一点?
TIA。
如何使用循环,迭代运行时可用的Resources
列表,然后在每次迭代时获取对象的锁定,这是一个示例,我用Object
类演示:
public static void main(String[] args) {
List<Object> list = new ArrayList<>();
list.addAll(Arrays.asList(new Object(), new Object(), new Object()));
Runnable run = () -> {
for(Object o: list) {
synchronized (o) {
System.out.println("Current thread " + Thread.currentThread().getName());
System.out.println(o.hashCode());
try {
Thread.sleep(2000);
}catch (InterruptedException ie){
ie.printStackTrace();
}
//do something useful
}
}
};
new Thread(run, "t1").start();
new Thread(run, "t2").start();
new Thread(run, "t3").start();
new Thread(run, "t4").start();
}
当一个线程获得对特定对象的锁定时,其他线程将等待它,但是它们可以自由地从for-each循环获取对下一个可用对象的锁定。
您可以为List接口编写自己的实现,并在列表中查询时锁定您的资源。
https://docs.oracle.com/javase/8/docs/api/java/util/List.html