简体   繁体   English

转换 wait & notifyAll 代码以使用 Java 1.5 锁定 object

[英]Convert wait & notifyAll code to use Java 1.5 Lock object

We use code that uses syncronized blocks around segments of code with a lot of wait and notifyAll() calls.我们使用在代码段周围使用同步块的代码,其中包含大量等待和 notifyAll() 调用。 We are trying to convert these to use Java 5 Lock.lock() and Lock.unlock() methods.我们正在尝试将这些转换为使用 Java 5 Lock.lock() 和 Lock.unlock() 方法。 How do I migrate this code to remove all the wait and notifyAll calls.如何迁移此代码以删除所有 wait 和 notifyAll 调用。 I do not know the equivalent to these using the new Locking features.我不知道这些使用新的锁定功能的等价物。

Any links with examples would be appreciated.任何带有示例的链接将不胜感激。

Thanks in Advance提前致谢

Eq., the following code needs to be converted to use Lock.lock() and lock.unlock The first part to remove the synchronized block is simple as I just need to call lock() method. Eq.,下面的代码需要转换为使用 Lock.lock() 和 lock.unlock 删除同步块的第一部分很简单,我只需要调用 lock() 方法。 The question is what can be done for the notifyAll() and wait methods.问题是 notifyAll() 和 wait 方法可以做什么。

     synchronized( LOCK )
            {
                while( !Thread.interrupted() )
                {
                 try
                    {

                        working = runRules();

                        if( !working )
                            LOCK.notifyAll();

                        LOCK.wait( working ? shortTimeout : longTimeout );
                    }
                    catch( final InterruptedException e )
                    {
                        Package.log.info( "Thread was interrupted.  Exiting.", e );
                        return;
                    }
                }
            }

Use the Condition s provided by the java.util.concurrent.locks package :使用java.util.concurrent.locks package 提供的Condition

 final Object monitor = ...

 ...

 synchronized (monitor) {

     while (!condition) monitor.wait();
     ... do something ...
 }

becomes:变成:

 final ReentrantLock lock = ...;
 final Condition cvar = lock.newCondition();

 ...

 lock.lock();

 try {

     while (!condition) cvar.await();
     ... do something ... 

 } finally {

     lock.unlock();
 }

The signalling side is pretty similar:信令方面非常相似:

 synchronized (monitor) {

      ... do something ...
      monitor.notify();
 }

becomes:变成:

 lock.lock();

 try {

     ... do something ...
     cvar.signalAll();

 } finally {

     lock.unlock();
 }

Use Condition objects provided by the Lock.newCondition() factory method.使用Lock.newCondition()工厂方法提供的Condition对象。 The waiting and notification aspects of an Object's monitor were factored out into this interface.对象监视器的等待和通知方面已被考虑到此接口中。

From a migration point of view:从迁移的角度来看:

  • wait() -> await() wait() -> await()
  • wait(long) -> await(long, TimeUnit.Millis) or awaitNanos(long * 10000000) wait(long) -> await(long, TimeUnit.Millis)awaitNanos(long * 10000000)
  • notify() -> signal() notify() -> signal()
  • notifyAll() -> signalAll() notifyAll() -> signalAll()

However, conditions are more powerful than monitors in several ways.然而,条件在几个方面比监视器更强大。 Firstly they are more fine grained, so you can have multiple conditions for different things.首先,它们的粒度更细,因此您可以为不同的事物设置多个条件。 If I have a bounded blocking collection for instance, I can have a condition for full and a condition for empty, and await and notify these separately as elements are added or removed.例如,如果我有一个有界阻塞集合,我可以有一个完整的条件和一个空的条件,并在添加或删除元素时分别等待和通知它们。

There are also additional await variants that allow you to await without being interrupted and await until a certain specific date (time).还有其他的await变体允许您在不被中断的情况下等待并等待到某个特定日期(时间)。

The javadocs of the Condition class are very good and describe it and its use in great detail. Condition class 的 javadocs 非常好,并且非常详细地描述了它及其使用。

Since this question is talking about notifyAll, i have tried some example of producer/consumer with phaser.由于这个问题是关于 notifyAll 的,所以我尝试了一些带有移相器的生产者/消费者示例。 I didn't used Lock, since that needs try/finally, condition object, and till unlock other thread will not work... etc...我没有使用锁,因为这需要尝试/最后,条件 object,直到解锁其他线程将无法工作......等等......

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.");
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM