寻找更好的方法来记录wait()和notify()方法

时间:2017-03-19 23:01:20

标签: java multithreading logging locking wrapper

每当调用并返回Object类中的wait,notify和notifyAll方法时,我都会尝试打印到控制台。为此,我创建了一个包装类,它代表lock对象调用wait,notify和notifyAll方法。然后我使用包装器上的方法而不是wait,notify和notifyAll。这是我最好的尝试,

Thread One运行Runnable r1

Runnable r1 = new Runnable() {
    @Override
    public void run() {
        synchronized (lock) {
            try {
                // wait not wrapped in while loop for brevity.
                //lock.wait(); 
                lock.objWrapper.waitNew(); // Use the wrapper method instead of wait()
            } catch (InterruptedException e) {}
        }
    }
};

线程2运行Runnable r2

Runnable r2 = new Runnable() {
    @Override
    public void run() {
        synchronized(lock) {
            //lock.notifyAll();
            lock.objWrapper.notifyAllNew(); // Use the wrapper method instead of notifyAll()
        }
    }
};

类Lock被定义为,

public class Lock {
    ObjWrapper objWrapper = new ObjWrapper(this);
    // shared data here
}

Lock lock = new Lock();

包装类定义为,

public class ObjWrapper {
    Object obj = null;

    ObjWrapper(Object obj) {
        System.out.println("New Object wrapper created: Thread: " + Thread.currentThread() + " at time: " + Instant.now());
        this.obj = obj;
    }

    public void waitNew() throws InterruptedException {
        System.out.println("Entering Object::wait: Thread: " + Thread.currentThread() + " at time: " + Instant.now());
        obj.wait();
        System.out.println("Exiting Object::wait: Thread: " + Thread.currentThread() + " at time: " + Instant.now());
    }

    public void notifyNew() {
        System.out.println("Entering Object::notify: Thread: " + Thread.currentThread() + " at time: " + Instant.now());
        obj.notify();
        System.out.println("Exiting Object::notify: Thread: " + Thread.currentThread() + " at time: " + Instant.now());
    }

    public void notifyAllNew() {
        System.out.println("Entering Object::notifyAll: Thread: " + Thread.currentThread() + " at time: " + Instant.now());
        obj.notifyAll();
        System.out.println("Exiting Object::notifyAll: Thread: " + Thread.currentThread() + " at time: " + Instant.now());
    }
}

最后,使用

启动线程
    Thread t1 = new Thread(r1);
    t1.setName("Thread One");
    t1.start();

    Thread t2 = new Thread(r2);
    t2.setName("Thread Two");
    t2.start();

控制台上的输出,

New Object wrapper created: Thread: Thread[main,5,main] at time: 2017-03-19T22:48:28.771Z
Entering Object::wait: Thread: Thread[Thread One,5,main] at time: 2017-03-19T22:48:28.844Z
Entering Object::notifyAll: Thread: Thread[Thread Two,5,main] at time: 2017-03-19T22:48:31.845Z
Exiting Object::notifyAll: Thread: Thread[Thread Two,5,main] at time: 2017-03-19T22:48:31.845Z
Exiting Object::wait: Thread: Thread[Thread One,5,main] at time: 2017-03-19T22:48:31.845Z

我的问题是,

  1. 还有其他更好的方法吗?
  2. 使用ObjWrapper时是否会出现任何边缘情况?
  3. 编辑:  我不是在寻找更好的方法来锁定物体。更好的方法是专门记录wait()notify()notifyAll()方法的调用。

1 个答案:

答案 0 :(得分:0)

关于问题1,我宁愿继承ReentrantLockCondition,然后覆盖信号等待方法,因为采用这种方法,无论如何,你失去了在方法上使用关键字synchronized的可能性。

关于问题2,我在这里可以看到的主要边缘情况是你受intrinsic lock和内在条件队列的约束。我认为一个很大的警告是,如果你想使用ReentrantLock和/或Condition,你将不得不编写新的包装器(这可能不是直截了当的),冒着引入更多复杂性的风险,还有更多问题。

现在您可能已经意识到,我建议坚持使用更高级别的API,即Latches,Semaphores,Barriers,ConcurrentCollection等等,并尽可能远离低级别的线程管理,因为它很快就会变得棘手。