首页 文章

转换wait&notifyAll代码以使用Java 1.5 Lock对象

提问于
浏览
5

我们使用在代码段周围使用同步块的代码,需要大量的wait和notifyAll()调用 . 我们正在尝试将这些转换为使用Java 5 Lock.lock()和Lock.unlock()方法 . 如何迁移此代码以删除所有wait和notifyAll调用 . 我不知道使用新的锁定功能相当于这些 .

任何与示例的链接将不胜感激 .

提前致谢

方程式,下面的代码需要转换为使用Lock.lock()和lock.unlock删除synchronized块的第一部分很简单,因为我只需要调用lock()方法 . 问题是可以为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;
                    }
                }
            }

3 回答

  • 7

    使用Conditions provided by the java.util.concurrent.locks package

    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();
     }
    
  • 4

    使用 Lock.newCondition() 工厂方法提供的Condition对象 . 对象监视器的等待和通知方面已被考虑到此接口中 .

    从迁移的角度来看:

    • wait() - > await()

    • wait(long) - > await(long, TimeUnit.Millis)awaitNanos(long * 10000000)

    • notify() - > signal()

    • notifyAll() - > signalAll()

    但是,条件在几个方面比监视器更强大 . 首先,它们更精细,因此您可以为不同的事物提供多种条件 . 例如,如果我有一个有界的阻塞集合,我可以有一个条件为满和条件为空,并等待并在添加或删除元素时单独通知它们 .

    还有其他 await 变体允许您等待而不会被中断并等待直到某个特定日期(时间) .

    Condition类的javadoc非常好,并且非常详细地描述它和它的用法 .

  • 0

    由于这个问题是关于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.");
        }
    }
    

相关问题