【问题标题】:Looking for a better way to log wait() and notify() methods寻找记录 wait() 和 notify() 方法的更好方法
【发布时间】:2017-08-11 03:04:52
【问题描述】:

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

线程一运行 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) {}
        }
    }
};

线程两个运行 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 时是否存在会中断的边缘情况?

编辑: 我不是在寻找更好的方法来锁定对象。只是更好的方法来记录wait()notify()notifyAll() 方法的调用。

【问题讨论】:

    标签: java multithreading logging locking wrapper


    【解决方案1】:

    关于问题 1,我宁愿继承 ReentrantLockCondition,然后重写 signalawait 方法,因为使用这种方法,无论如何你都会失去可以使用关键字 synchronized on 方法。

    关于问题 2,我在这里看到的主要边缘情况是您受 intrinsic lock 和内在条件队列的约束。在我看来,一个重要的警告是,如果你想使用ReentrantLock 和/或Condition,你将不得不编写新的包装器(这可能并不简单),这可能会带来更多的复杂性和更多的问题。

    现在您可能已经知道,我宁愿建议坚持使用更高级别的 API,即锁存器、信号量、障碍、ConcurrentCollection 等等,并尽可能远离低级别线程管理,因为它很快就会变得很棘手。

    【讨论】:

    • 感谢您的回复。请看我的编辑。我对 Object 类中的 wait()notify() 方法特别感兴趣,想知道它们何时被调用。
    • 当您调用它们时会调用它们,这就是为什么我不确定包装部分的原因。我认为您正在尝试在 notify/notifyAll 调用后检查线程何时开始运行,如果我错了,请纠正我,这是一个更广泛的话题
    • 你是对的,当线程从运行状态变为等待状态时,我想要一个线程句柄,反之亦然。我拥有的代码中唯一的钩子是调试语句。考虑到这些限制,我只剩下记录 waitnotify 的调用了
    猜你喜欢
    • 2019-02-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-04
    • 2017-06-17
    相关资源
    最近更新 更多