所以我的代码与此类似
synchronized(objectOne){ do stuff }
synchronized(objectTwo){ do stuff }
问题是,即使objectOne
的锁定可用,程序也会等待objectTwo
上的锁定。我要做的就是说:尝试同时锁定objectOne
和objectTwo
,无论你先获得哪个锁都可以锁定该锁。我想出了一个解决方案,但我觉得它很苛刻,我想知道是否有人有更好的想法。
这是我的想法:启动2个线程,每个线程等待锁定,然后主线程将等待CountDownLatch。所以你最终得到这样的东西:
CountDownLatch latch = new CountDownLatch(2);
new Thread(new Runnable(){
public void run(){
synchronized(objectOne) { do stuff }
latch.countDown();
}).start();
new Thread(new Runnable(){
public void run(){
synchronized(objectTwo) { do stuff }
latch.countDown();
}).start();
latch.await();
答案 0 :(得分:5)
答案 1 :(得分:2)
您可能希望拥有2个作业队列,每个队列轮询2个线程并执行作业。
对于与objectOne相关的作业,将其放入队列#1;队列#2中与objectTwo相关的作业。
worker1.queue.put( new Runnable(){ public void run() { do stuff } } );
worker2.queue.put( new Runnable(){ public void run() { do stuff } } );
----
class Worker extends Thread
BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>();
public void run()
while(true)
queue.take().run();
答案 2 :(得分:0)
根据stuff
的数量,分离多个线程来执行操作可能会带来更多开销。如果stuff
是足够快的操作,那么在单个线程中执行操作可能是最好的。你必须知道它的时间。
答案 3 :(得分:0)
我有点像你的黑客,至少如果它是一次性的情况。那说......
如果你经常做这类事情并想要一些事情,那就不那么苛刻了,我建议ExecutorService#invokeAll()。这将获取一个Callables列表,在线程池中执行它们并阻塞,直到它们全部完成。
草图:
ExecutorService es = Executors.newCachedThreadPool(); // for example...
List<Future<Void>> results = es.invokeAll(new ArrayList {{
add(new Callable<Void> {
public Void call() { synchronized(objectOne) { do stuff } }
});
add(new Callable<Void> {
public Void call() { synchronized(objectTwo) { do stuff } }
});
}});
// both Callables are done when you get here
这显然假设您可以在应用中的此时从不同的线程调用这些方法。如果由于某种原因你需要从同一个帖子中调用两者,我认为你注定要使用tryLock
并忙于等待Bhesh Gurung的回答中所讨论的。