package com.bao.examples.thread;
import java.util.*;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class SerializedOperBooker
{
private static Log log = LogFactory.getLog(SerializedOperBooker.class);
//Simple init way to avoid multi-threading violation.
private static SerializedOperBooker instance = new SerializedOperBooker();
//The book data
private Map<String, LinkedList> bookMap = null;
private SerializedOperBooker()
{
bookMap = new HashMap<String, LinkedList>();
}
public static SerializedOperBooker getInstance()
{
return instance;
}
public synchronized void book(String operObjName, Object bookeeID)
{
LinkedList que = null;
//No other operations to this object
if(!bookMap.containsKey(operObjName))
{
que = new LinkedList();
bookMap.put(operObjName, que);
}
//there are some other operations to this object
else
{
que = bookMap.get(operObjName);
}
que.add(bookeeID);
log.info("[book]: operObjName=" + operObjName + ", bookeeID=" + bookeeID);
}
public synchronized void unbook(String operObjName)
{
LinkedList que = bookMap.get(operObjName);
if(que == null || que.isEmpty())
{
//For normal usage, this should NOT be happened. Just log here for exception.
log.fatal("fatal error. que is " + que + ", when unbook " + operObjName);
return;
}
que.remove();
if(que.isEmpty())
{
bookMap.remove(operObjName);
}
log.info("[unbook]: operObjName=" + operObjName);
notifyAll();
}
public synchronized void checkExecutable(String operObjName, Object bookeeID)
{
LinkedList que = bookMap.get(operObjName);
if(que == null || que.isEmpty())
{
//For normal usage, this should NOT be happened. Just log here for exception.
log.fatal("fatal error. que is " + que + ", when checkExecutable " + operObjName);
return;
}
Object bookee = null;
for(bookee = que.peek(); bookee != bookeeID; bookee = que.peek())
{
//The bookee should not be null
if(bookee == null)
{
//For normal usage, this should NOT be happened. Just log here for exception.
log.fatal("fatal error. bookee is null when checkExecutable " + operObjName);
return;
}
log.info("The object [" + operObjName + "] is now operated by [" + bookee + "], wait.");
try
{
//Wait until the condition changed
wait();
}
catch(InterruptedException e)
{
//ignore
}
}
log.info("It's the turn of [" + bookeeID + "] now for object [" + operObjName + "]");
}
}