我需要从数据库加载配置映射。配置映射表示为
Hashtable<String, Hashtable<String,String>>
我们不能一开始就加载映射,因为我们依赖于另一个war应用程序进行数据库连接。所以,该映射被装载在类(singleton)的所述第一呼叫到配置ResourcesStorage
实施ServletContextListener
。同时,重置JSPreset()
在此侦听器中调用静态方法。我使用reentrant
锁添加了同步。我只锁定重置,因为不同的线程应该能够同时检索数据。但是,这不能很好地工作。
我正进入(状态
IllegalMonitorStateException on notFull.await();
java.lang.IllegalMonitorStateException
at java.util.concurrent.locks.ReentrantLock$Sync.tryRelease(ReentrantLock.java:127)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.release(AbstractQueuedSynchronizer.java:1175)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.fullyRelease(AbstractQueuedSynchronizer.java:1606)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:1922)
我的设计正确吗?
import java.util.Hashtable;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class ResourcesStorage implements ServletContextListener {
private static ResourcesStorage instance;
protected static Log log = LogFactory.getLog(ResourcesStorage.class);
protected Hashtable<String, Hashtable<String,String>> DBsettings =new Hashtable <String, Hashtable<String,String>>();
private ServletContext context = null;
private boolean isLoading = false;
public synchronized boolean isLoading() {
return isLoading;
}
public synchronized void setLoading(boolean isLoading) {
this.isLoading = isLoading;
}
private Lock lock = new ReentrantLock();
private Condition notFull = lock.newCondition();
public void contextDestroyed(ServletContextEvent arg0) {}
public void contextInitialized(ServletContextEvent event) {
this.context = event.getServletContext();
//initialize the static reference _instance
instance=this;
reloadAllSettings();
}
public Hashtable<String, Hashtable<String,String>> getDBSettings()
{
return DBsettings;
}
public static String getSettings(String groupName, String keyName)
{
ResourcesStorage instance = ResourcesStorage.getInstance();
Hashtable<String, Hashtable<String,String>> dbsettings = instance.getDBSettings();
Hashtable<String,String> group =(Hashtable<String,String>) dbsettings.get(groupName);
if(group!=null && !group.isEmpty())
return group.get(keyName);
else
return null;
}
public String getValueSettings (String groupName, String keyName)
{
try
{
while (isLoading() == false)
{
notFull.await();
}
Hashtable<String,String> group =(Hashtable<String,String>) DBsettings.get(groupName);
if(group!=null && !group.isEmpty())
{
return group.get(keyName);
}
else
{
return null;
}
}
catch (Exception e)
{
log.error("getValueSetting", e);
}
return null;
}
public static void reSet(){
ResourcesStorage instance = ResourcesStorage.getInstance();
instance.reloadAllSettings();
}
public void reloadAllSettings(){
lock.lock();
setLoading(true);
try
{
// .....
//getting resources from the database
setLoading(false);
notFull.signal();
} catch (Exception e) {
//...
}
finally
{
lock.unlock();
}
}
public static ResourcesStorage getInstance()
{
return instance;
}
public ServletContext getContext() {
return context;
}
public void setContext(ServletContext context) {
this.context = context;
}
}
意见建议:
设置已加载或尚未加载。如果已加载它们,请使用它们。
如果尚未加载,请调用同步方法。这是您唯一需要的锁定机制。在方法中检查是否已加载它们(由于竞争条件),如果已加载,请返回。否则,请在阻止其他正在等待的线程时获取它们。
确保将设置引用保留在可变变量中。
编辑:
我的建议不支持让多个线程同时加载相同的数据。这是故意的。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句