Android 未调用 notify() 方法

Android notify() method is not called

我正在尝试使用 notify() 和 wait()。这是我想要的 class。 当我尝试调用 addNewItem() 时遇到问题。如果我先调用 tryToReadItem() 然后再调用 addNewItem() 方法,则不会打印该日志。请注意,我的 DemoClass 是单例。

public class DemoClass {

private static final String TAG = "DemoClass";

private static DemoClass instance;
private Object lock = new Object();
private static Thread executor;
private static Runnable reader;
static MyQueue queue;


private DemoClass() {
    queue = MyQueue.getInstance();
    reader = new Runnable() {

        @Override
        public void run() {
            tryToReadRequest();
        }
    };

}

public static DemoClass getInstance() {
   if (null == instance) {
        instance = new RequestExecutor();
        executor = new Thread(reader);
        executor.run();
    }
    return instance;
}

public boolean addNewItem() {
    synchronized (lock) {
        lock.notify();  // executor will be run
        Log.i(TAG, "executor run...");
    }
    return true;
}

public void tryToReadItem() {

    try {
        while (true) {
            synchronized (lock) {
                if (queue.checkTopValue() == null) {
                    Log.v(TAG, "queue is empty");
                    lock.wait();
                } else {
                    //TODO other code...
                }

            }
        }
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}
}

这是 class 的用法:

DemoClass executor = DemoClass.getInstance();
boolean bool = executor.addNewItem();

我是不是漏掉了什么?

编辑:我刚刚更改了我的代码。现在 tryToReadRequest() 在队列不为空的情况下连续执行。但我的问题是 lock.notify(); 行没有执行。

这段代码有很多问题

首先

        if (queue.checkTopValue() == null) {
            Log.v(TAG, "queue is empty");
            lock.wait();
        }

取决于official documentation

Note: Always invoke wait inside a loop that tests for the condition being waited for. Don't assume that the interrupt was for the particular condition you were waiting for, or that the condition is still true.

你的 DemoClassSingleton。但不是线程安全Singleton

因为多个线程可以在同一时间传递null ==实例条件

   if (null == instance) {
        instance = new RequestExecutor();
        executor = new Thread(reader);
        executor.run();
    }

正确的方法是额外检查同步块并使用 volatile 实例。

因此将 volatile 添加到实例中

private static volatile DemoClass instance;

并将 getInstance() 方法重写为如下内容

public static DemoClass getInstance() {
    DemoClass localInstance = instance;

    if (localInstance == null) {
        synchronized (DemoClass.class) {
            localInstance = instance;
            if (localInstance == null) {
                localInstance = new DemoClass();
                instance = localInstance;
                executor = new Thread(reader);
                executor.run();
            }
        }
    }
    return localInstance;
}

注意,您可以只在同步块中保留检查,但这会使 getInstance 方法太慢。