我的 Android 应用程序中有两个线程,它们实际上是生产者/消费者关系;生产者线程(Thread 的子类)用对象填充缓冲区,消费者线程(AsyncTask 的子类)在该缓冲区上操作。从这里的 Java 保护锁并发教程中,我收集到我可以使用“第三方”线程来协调这个交换,但理想情况下,我希望能够通过调用等待来关闭消费者线程本身,因为它唯一真正的任务是在缓冲区被生产者填充后对其进行操作。当且仅当生产者完成完全填充缓冲区时,生产者将通过调用 notify 或 notifyAll 将其唤醒。为了促进这一点,我分别为我的消费者和生产者进行了以下配置:
消费者.java
public class Consumer extends AsyncTask<Object,Integer,Object>{
private String TAG = "Consumer";
private String SUBCLASS_TAG = "";
private String FUNCTION_TAG = "";
private int UUID = MasterSemaphore.getAndIncrementUuidTracker();
public synchronized void getMonitorForNotification(){
FUNCTION_TAG = "::getMonitorForNotification";
while(MasterSemaphore.getIsBufferingMap().get(UUID)){
try {
Log.i(TAG+SUBCLASS_TAG+FUNCTION_TAG, "about to wait...");
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
FUNCTION_TAG = "::getMonitorForNotification";
Log.i(TAG+SUBCLASS_TAG+FUNCTION_TAG, "Received notification!");
}
@Override
protected Object doInBackground(Object... bgTaskResources) {
Producer hProducer = (Producer)bgTaskResources[0];
//The next call is supposed to freeze this thread's execution via an invocation
//of wait-- see the Producer::populateBuffer(...) method
hProducer.populateBuffer(5,this);
//...handle other AsyncTask callbacks
生产者.java
//..snip
public synchronized int populateBuffer(int numElements, Consumer externalTaskCaller){
TAG = "Producer"
SUBCLASS_TAG = "";
FUNCTION_TAG = "::populateBuffer";
//First set the bufferingMap over the external caller's UUID to true
MasterSemaphore.getIsBufferingMap().put(externalTaskCaller.getUUID(), true);
Log.i(TAG+SUBCLASS_TAG+FUNCTION_TAG, "just set "+externalTaskCaller.getUUID()+" Key in
the bufferingMap to true");
//Next acquire the monitor of the external caller, and tell it to wait for notification
externalTaskCaller.getMonitorForNotification();
Log.i(TAG+SUBCLASS_TAG+FUNCTION_TAG, "just acquired a monitor lock on
externalCaller"+externalTaskCaller.toString()+", hopefully");
int elementsProduced = 0;
for (int i=0;i<numElements;i++){
mvElemVector.add(new Element());
Log.i(TAG+SUBCLASS_TAG+FUNCTION_TAG, "just created element number "+i+" of
"+numElements);
elementsProduced++;
}
if(externalTaskCaller != null){
MasterSemaphore.getIsBufferingMap().put(externalTaskCaller.getUUID(), false);
Log.i(TAG+SUBCLASS_TAG+FUNCTION_TAG, "just set "+externalTaskCaller.getUUID()+" Key
in the bufferingMap to false since our buffer writing is done");
externalTaskCaller.notifyAll();
Log.i(TAG+SUBCLASS_TAG+FUNCTION_TAG, "just notified the external caller
"+externalTaskCaller.toString());
}
return threadsProduced;
}
//..snip
当我对此功能运行单元测试时看到的结果(基本上只是创建并启动生产者线程,然后创建并执行消费者任务)仅返回日志条目:
01-02 09:01:53.530: I/Producer::populateBuffer(21932): just set 0 Key in the
bufferingMap to true
01-02 09:01:53.530:I/Consumer::getMonitorForNotification(21932): about to wait...
就是这样......所以我们要
externalTaskCaller.getMonitorForNotification();
但永远达不到
Log.i(TAG+SUBCLASS_TAG+FUNCTION_TAG, "just acquired a monitor lock on
externalCaller"+externalTaskCaller.toString()+", hopefully");
我的等待通知实现有什么问题?是否需要像链接教程中的 Drop 对象这样的“第三方”对象来协调生产者/消费者交换?