Java Guavache expireAfterWrite()导致阻塞线程过多

Java Guavache expireAfterWrite()导致阻塞线程过多,java,multithreading,guava,contention,Java,Multithreading,Guava,Contention,我们有一个用例,我们的数据在一段时间后变得陈旧。因此,我们选择了expireAfterWrite缓存逐出策略。但是,这会导致线程池中有太多被阻塞的线程。你知道为什么会发生这种情况吗?有没有办法避免这种情况 线程池日志示例: Debugger attached successfully. Server compiler detected. JVM version is 25.112-b15 Deadlock Detection: No deadlocks found. Thread 7546:

我们有一个用例,我们的数据在一段时间后变得陈旧。因此,我们选择了expireAfterWrite缓存逐出策略。但是,这会导致线程池中有太多被阻塞的线程。你知道为什么会发生这种情况吗?有没有办法避免这种情况

线程池日志示例:

Debugger attached successfully.
Server compiler detected.
JVM version is 25.112-b15
Deadlock Detection:

No deadlocks found.

Thread 7546: (state = BLOCKED)
 - sun.misc.Unsafe.park(boolean, long) @bci=0 (Compiled frame; information may be imprecise)
 - java.util.concurrent.locks.LockSupport.parkNanos(java.lang.Object, long) @bci=20, line=215 (Compiled frame)
 - java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill(java.util.concurrent.SynchronousQueue$TransferStack$SNode, boolean, long) @bci=160, line=460 (Compiled frame)
 - java.util.concurrent.SynchronousQueue$TransferStack.transfer(java.lang.Object, boolean, long) @bci=102, line=362 (Compiled frame)
 - java.util.concurrent.SynchronousQueue.poll(long, java.util.concurrent.TimeUnit) @bci=11, line=941 (Compiled frame)
 - java.util.concurrent.ThreadPoolExecutor.getTask() @bci=134, line=1066 (Compiled frame)
 - java.util.concurrent.ThreadPoolExecutor.runWorker(java.util.concurrent.ThreadPoolExecutor$Worker) @bci=26, line=1127 (Compiled frame)
 - java.util.concurrent.ThreadPoolExecutor$Worker.run() @bci=5, line=617 (Compiled frame)
 - java.lang.Thread.run() @bci=11, line=745 (Compiled frame)

Locked ownable synchronizers:
    - None

Thread 1268: (state = BLOCKED)
 - sun.misc.Unsafe.park(boolean, long) @bci=0 (Compiled frame; information may be imprecise)
 - java.util.concurrent.locks.LockSupport.park(java.lang.Object) @bci=14, line=175 (Interpreted frame)
 - java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt() @bci=1, line=836 (Interpreted frame)
 - java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedInterruptibly(int) @bci=72, line=997 (Interpreted frame)
 - java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(int) @bci=24, line=1304 (Compiled frame)
 - com.amazon.coral.google.common.util.concurrent.AbstractFuture$Sync.get() @bci=2 (Compiled frame)
 - com.amazon.coral.google.common.util.concurrent.AbstractFuture.get() @bci=4 (Compiled frame)
 - com.amazon.coral.google.common.util.concurrent.Uninterruptibles.getUninterruptibly(java.util.concurrent.Future) @bci=3 (Compiled frame)
 - com.amazon.coral.google.common.cache.LocalCache$LoadingValueReference.waitForValue() @bci=4 (Interpreted frame)
 - com.amazon.coral.google.common.cache.LocalCache$Segment.waitForLoadingValue(com.amazon.coral.google.common.cache.LocalCache$ReferenceEntry, java.lang.Object, com.amazon.coral.google.common.cache.LocalCache$ValueReference) @bci=44 (Interpreted frame)
 - com.amazon.coral.google.common.cache.LocalCache$Segment.get(java.lang.Object, int, com.amazon.coral.google.common.cache.CacheLoader) @bci=122 (Interpreted frame)
 - com.amazon.coral.google.common.cache.LocalCache.get(java.lang.Object, com.amazon.coral.google.common.cache.CacheLoader) @bci=17 (Compiled frame)
 - com.amazon.coral.google.common.cache.LocalCache.getOrLoad(java.lang.Object) @bci=6 (Compiled frame)
 - com.amazon.coral.google.common.cache.LocalCache$LocalLoadingCache.get(java.lang.Object) @bci=5 (Compiled frame)
 - com.amazon.csapp.services.SmartVideoCacheService.getVideos(com.amazon.csapp.utils.MetricsContext, com.amazon.csapp.utils.AmazonRequestInfo) @bci=33, line=214 (Compiled frame)
 - com.amazon.csapp.rest.resource.v2.VideoResource.getVideos(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String) @bci=67, line=56 (Interpreted frame)
 - sun.reflect.GeneratedMethodAccessor90.invoke(java.lang.Object, java.lang.Object[]) @bci=88 (Compiled frame)
 - sun.reflect.DelegatingMethodAccessorImpl.invoke(java.lang.Object, java.lang.Object[]) @bci=6, line=43 (Compiled frame)
 - java.lang.reflect.Method.invoke(java.lang.Object, java.lang.Object[]) @bci=56, line=498 (Compiled frame)
 - org.glassfish.jersey.server.model.internal.ResourceMethodInvocationHandlerFactory$1.invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[]) @bci=3, line=81 (Interpreted frame)
 - org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.invoke(java.lang.Object, java.lang.Object[]) @bci=39, line=128 (Interpreted frame)
 - org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$TypeOutInvoker.doDispatch(java.lang.Object, javax.ws.rs.core.Request) @bci=6, line=195 (Interpreted frame)
 - org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(java.lang.Object, org.glassfish.jersey.server.ContainerRequest) @bci=3, line=94 (Compiled frame)
 - org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(org.glassfish.jersey.server.ContainerRequest, java.lang.Object) @bci=13, line=353 (Compiled frame)
 - org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(org.glassfish.jersey.server.ContainerRequest) @bci=103, line=343 (Interpreted frame)
 - org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(java.lang.Object) @bci=5, line=102 (Interpreted frame)
 - org.glassfish.jersey.server.ServerRuntime$1.run() @bci=198, line=237 (Compiled frame)
 - org.glassfish.jersey.internal.Errors$1.call() @bci=4, line=271 (Compiled frame)
 - org.glassfish.jersey.internal.Errors$1.call() @bci=1, line=267 (Compiled frame)
 - org.glassfish.jersey.internal.Errors.process(java.util.concurrent.Callable, boolean) @bci=36, line=315 (Compiled frame)
 - org.glassfish.jersey.internal.Errors.process(org.glassfish.jersey.internal.util.Producer, boolean) @bci=2, line=297 (Compiled frame)
 - org.glassfish.jersey.internal.Errors.process(java.lang.Runnable) @bci=9, line=267 (Compiled frame)
 - org.glassfish.jersey.process.internal.RequestScope.runInScope(java.lang.Runnable) @bci=25, line=322 (Interpreted frame)
 - org.glassfish.jersey.server.ServerRuntime.process(org.glassfish.jersey.server.ContainerRequest) @bci=22, line=211 (Interpreted frame)
 - org.glassfish.jersey.server.ApplicationHandler.handle(org.glassfish.jersey.server.ContainerRequest) @bci=5, line=979 (Compiled frame)
 - org.glassfish.jersey.servlet.WebComponent.service(java.net.URI, java.net.URI, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) @bci=115, line=344 (Compiled frame)
 - org.glassfish.jersey.servlet.ServletContainer.service(java.net.URI, java.net.URI, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) @bci=9, line=372 (Compiled frame)
 - org.glassfish.jersey.servlet.ServletContainer.service(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) @bci=321, line=335 (Compiled frame)
 - com.amazon.csapp.servlet.JerseyServletContainer.service(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) @bci=15, line=26 (Compiled frame)
 - org.glassfish.jersey.servlet.ServletContainer.service(javax.servlet.ServletRequest, javax.servlet.ServletResponse) @bci=39, line=218 (Compiled frame)
 - org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse) @bci=376, line=290 (Compiled frame)
 - org.apache.catalina.core.ApplicationFilterChain.doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse) @bci=101, line=206 (Compiled frame)
 - org.apache.catalina.core.StandardWrapperValve.invoke(org.apache.catalina.connector.Request, org.apache.catalina.connector.Response) @bci=804, line=233 (Compiled frame)
 - org.apache.catalina.core.StandardContextValve.invoke(org.apache.catalina.connector.Request, org.apache.catalina.connector.Response) @bci=365, line=191 (Compiled frame)
 - org.apache.catalina.authenticator.AuthenticatorBase.invoke(org.apache.catalina.connector.Request, org.apache.catalina.connector.Response) @bci=327, line=470 (Compiled frame)
 - org.apache.catalina.core.StandardHostValve.invoke(org.apache.catalina.connector.Request, org.apache.catalina.connector.Response) @bci=64, line=127 (Compiled frame)
 - org.apache.catalina.valves.ErrorReportValve.invoke(org.apache.catalina.connector.Request, org.apache.catalina.connector.Response) @bci=6, line=103 (Compiled frame)
 - com.amazon.tomcat.valves.QueryLogValve.invoke(org.apache.catalina.connector.Request, org.apache.catalina.connector.Response) @bci=47, line=78 (Compiled frame)
 - org.apache.catalina.valves.AccessLogValve.invoke(org.apache.catalina.connector.Request, org.apache.catalina.connector.Response) @bci=24, line=617 (Compiled frame)
 - org.apache.catalina.core.StandardEngineValve.invoke(org.apache.catalina.connector.Request, org.apache.catalina.connector.Response) @bci=42, line=109 (Compiled frame)
 - org.apache.catalina.connector.CoyoteAdapter.service(org.apache.coyote.Request, org.apache.coyote.Response) @bci=158, line=293 (Compiled frame)
 - org.apache.coyote.http11.Http11Processor.process(java.net.Socket) @bci=545, line=859 (Compiled frame)
 - org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(java.net.Socket) @bci=73, line=610 (Compiled frame)
 - org.apache.tomcat.util.net.JIoEndpoint$Worker.run() @bci=41, line=503 (Compiled frame)
 - java.lang.Thread.run() @bci=11, line=745 (Compiled frame)
您可能应该更频繁地向缓存的值中添加。正如Ben Manes建议的那样,配置一个低于过期阈值的
refreshAfterWrite
,也会有所帮助,但您需要覆盖
reload()
,以异步完成工作

代码中也可能存在热点,导致多个单独的路径试图同时命中相同的缓存键。如果您不希望出现这种行为(例如,您希望一次大约有一个线程访问一个密钥),那么您可能需要调查是否有一些丢失的锁定语义导致太多线程同时从缓存中读取,或者是导致热点的不同原因,例如异常的请求模式。

(1)您可以添加
refreshAfterWrite
以隐藏加载时间,(2)可能存在导致线程卡住的错误