首页 / 缓存 / java-内存中缓存的线程安全实现
java-内存中缓存的线程安全实现
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了java-内存中缓存的线程安全实现,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含4655字,纯文字阅读大概需要7分钟。
内容图文
import java.io.IOException;
import java.lang.ref.SoftReference;
import java.net.URI;
import java.security.cert.CRLException;
import java.security.cert.CertificateException;
import java.security.cert.X509CRL;
import java.security.cert.X509Certificate;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.naming.NamingException;
import org.joda.time.DateTime;
import org.kp.oppr.esb.logger.Logger;
import org.springframework.beans.factory.annotation.Autowired;
public class CachedCrlRepository {
private static final Logger LOGGER = new Logger("CachedCrlRepository");
private final Map<URI, SoftReference<X509CRL>> crlCache = Collections
.synchronizedMap(new HashMap<URI, SoftReference<X509CRL>>());;
private static int DEFAULT_CACHE_AGING_HOURS;
@Autowired
private DgtlSgntrValidator validator;
@Autowired
private CrlRepository crlRepository;
public X509CRL findCrl(URI crlUri, X509Certificate issuerCertificate,
Date validationDate) throws DigitalValdiationException,
CertificateException, CRLException, IOException, NamingException {
SoftReference<X509CRL> crlRef = this.crlCache.get(crlUri);
if (null == crlRef) {
LOGGER.info("Key CRL URI : " + crlUri + " not found in the cache " );
return refreshCrl(crlUri, issuerCertificate, validationDate);
}
X509CRL crl = crlRef.get();
if (null == crl) {
LOGGER.info("CRL Entry garbage collected: " + crlUri);
return refreshCrl(crlUri, issuerCertificate, validationDate);
}
if (validationDate.after(crl.getNextUpdate())) {
LOGGER.info("CRL URI no longer valid: " + crlUri);
LOGGER.info("CRL validation date: " + validationDate + " is after CRL next update date: " + crl.getNextUpdate());
return refreshCrl(crlUri, issuerCertificate, validationDate);
}
Date thisUpdate = crl.getThisUpdate();
LOGGER.info("This update " + thisUpdate);
/*
* The PKI the nextUpdate CRL extension indicates 7 days. The
* actual CRL refresh rate is every 3 hours. So it's a bit dangerous to
* only base the CRL cache refresh strategy on the nextUpdate field as
* indicated by the CRL.
*/
DateTime cacheMaturityDateTime = new DateTime(thisUpdate)
.plusHours(DEFAULT_CACHE_AGING_HOURS);
LOGGER.info("Cache maturity Date Time " + cacheMaturityDateTime);
if (validationDate.after(cacheMaturityDateTime.toDate())) {
LOGGER.info("Validation date: " + validationDate + " is after cache maturity date: " + cacheMaturityDateTime.toDate());
return refreshCrl(crlUri, issuerCertificate, validationDate);
}
LOGGER.info("using cached CRL: " + crlUri);
return crl;
}
public static int getDEFAULT_CACHE_AGING_HOURS() {
return DEFAULT_CACHE_AGING_HOURS;
}
public static void setDEFAULT_CACHE_AGING_HOURS(int dEFAULT_CACHE_AGING_HOURS) {
DEFAULT_CACHE_AGING_HOURS = dEFAULT_CACHE_AGING_HOURS;
}
private X509CRL refreshCrl(URI crlUri, X509Certificate issuerCertificate,
Date validationDate) throws DigitalValdiationException,
CertificateException, CRLException, IOException, NamingException {
X509CRL crl = crlRepository.downloadCRL(crlUri.toString());
this.crlCache.put(crlUri, new SoftReference<X509CRL>(crl));
return crl;
}
}
我有此类CachedCrlrepository,用于存储来自特定提供程序的CRL列表.我想知道我的实现是否是线程安全的,或者我在这里缺少什么.缓存用于Web服务,因此它是多线程的.
我对此特定方法表示怀疑
private X509CRL refreshCrl(URI crlUri, X509Certificate issuerCertificate,
Date validationDate) throws DigitalValdiationException,
CertificateException, CRLException, IOException, NamingException {
X509CRL crl = crlRepository.downloadCRL(crlUri.toString());
this.crlCache.put(crlUri, new SoftReference<X509CRL>(crl));
return crl;
}
我认为这条线需要同步
this.crlCache.put(crlUri, new SoftReference<X509CRL>(crl));
synchronized(this)
{
this.crlCache.put(crlUri, new SoftReference<X509CRL>(crl));
}
我看到的另一个问题是,运行GC后,缓存仍在内存中保留该条目.它从不执行这些代码行
if (null == crl) {
LOGGER.info("CRL Entry garbage collected: " + crlUri);
return refreshCrl(crlUri, issuerCertificate, validationDate);
}
解决方法:
通常,在期望大量流量和对对象的高并发访问(在本例中为crlCache)的情况下,不应使用同步Map.对于每个读取或写入线程,每个线程将在另一个线程之后等待,并且负载很重,线程计数将增加,最终服务器将崩溃.您可以查看ConcurrentHashMap.它旨在在这种情况下有效地工作.
您的第二点:
synchronized(this)
{
this.crlCache.put(crlUri, new SoftReference<X509CRL>(crl));
}
当前代码根本不需要,因为put方法已经同步.
对于最小的更改,请更换
private final Map<URI, SoftReference<X509CRL>> crlCache = Collections
.synchronizedMap(new HashMap<URI, SoftReference<X509CRL>>());;
与
private final ConcurrentHashMap<URI, SoftReference<X509CRL>> crlCache = new ConcurrentHashMap<URI, SoftReference<X509CRL>>();
最后,使用SoftReference很好,但是有更好的选择. Google的Guava是一个非常强大且高效的缓存生成器.
内容总结
以上是互联网集市为您收集整理的java-内存中缓存的线程安全实现全部内容,希望文章能够帮你解决java-内存中缓存的线程安全实现所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。