转换wait&notifyAll代码以使用Java 1.5 Lock对象
我们使用在代码段周围使用同步块的代码,需要大量的wait和notifyAll()调用。 我们正在尝试将这些转换为使用Java 5 Lock.lock()和Lock.unlock()方法。 如何迁移此代码以删除所有wait和notifyAll调用。 我不知道使用新的锁定function相当于这些。
任何与示例的链接将不胜感激。
提前致谢
方程式,下面的代码需要转换为使用Lock.lock()和lock.unlock删除synchronized块的第一部分很简单,因为我只需要调用lock()方法。 问题是可以为notifyAll()和wait方法做些什么。
同步(LOCK) { while(!Thread.interrupted()) { 尝试 { working = runRules(); 如果(!工作) LOCK.notifyAll(); LOCK.wait(工作?shortTimeout:longTimeout); } catch(最终InterruptedException e) { Package.log.info(“线程被中断。退出。”,e); 返回; } } }
使用java.util.concurrent.locks
包提供的Condition
:
final Object monitor = ... ... synchronized (monitor) { while (!condition) monitor.wait(); ... do something ... }
变为:
final ReentrantLock lock = ...; final Condition cvar = lock.newCondition(); ... lock.lock(); try { while (!condition) cvar.await(); ... do something ... } finally { lock.unlock(); }
信号方面非常相似:
synchronized (monitor) { ... do something ... monitor.notify(); }
变为:
lock.lock(); try { ... do something ... cvar.signalAll(); } finally { lock.unlock(); }
使用Lock.newCondition()
工厂方法提供的Condition
对象。 对象监视器的等待和通知方面已被考虑到此接口中。
从迁移的角度来看:
-
wait()
– >await()
-
wait(long)
– >await(long, TimeUnit.Millis)
或awaitNanos(long * 10000000)
-
notify()
– >signal()
-
notifyAll()
– >signalAll()
但是,条件在几个方面比监视器更强大。 首先,它们更精细,因此您可以为不同的事物提供多种条件。 例如,如果我有一个有界阻塞集合,我可以有一个条件为满和条件为空,并等待并在添加或删除元素时单独通知它们。
还有一些额外的await
变体允许您等待而不会被中断并等待直到某个特定日期(时间)。
Condition
类的javadoc非常好,并且非常详细地描述它和它的用法。
由于这个问题是关于notifyAll,我尝试了一些生产者/消费者与移相器的例子。 我没有使用过Lock,因为那需要try / finally,条件对象,直到解锁其他线程都行不通……等等……
import java.util.concurrent.Phaser; public class ProducerConsumerExample { Phaser producer; Phaser consumers; volatile String array[]; public void init() { producer = new Phaser(5); consumers = new Phaser(5); Consumer l1 = new Consumer("Consumer_1"); l1.setDaemon(true); l1.start(); Consumer l2 = new Consumer("Consumer_2"); l2.setDaemon(true); l2.start(); Consumer l3 = new Consumer("Consumer_3"); l3.setDaemon(true); l3.start(); Consumer l4 = new Consumer("Consumer_4"); l4.setDaemon(true); l4.start(); } class Consumer extends Thread { Consumer(String name) { super(name); } private void printMethod(String i) { System.out.println(Thread.currentThread().getName() + " " + i); } public void run() { while (true) { //make the consumers sleep till producer produces consumers.arriveAndAwaitAdvance(); for (int i = 0; i < array.length; i++) { printMethod(array[i]); } //alert the producer to start producer.arriveAndAwaitAdvance(); System.out.println(Thread.currentThread().getName() + " thread wakeup but will stuck with consumers.arriveAndAwaitAdvance!"); } } } public void run() { for (int j = 0; j < 3; j++) { array = new String[5]; for (int i = 0; i < array.length; i++) { array[i] = "Phase_" + (j + 1) + " Count_" + (i + 1); } System.out.println("Main thread pushed data."); //alert the consumers to start consumers.arriveAndAwaitAdvance(); //make the producer sleep till all the consumer consumes producer.arriveAndAwaitAdvance(); System.out.println("Main thread wakeup and will start pushing data..."); } } public static void main(String[] args) { ProducerConsumerExample sch = new ProducerConsumerExample(); sch.init(); sch.run(); System.out.println("Main thread completed, producing data."); } }