从单例 EJB 到无状态会话 Bean 的锁传播
Lock propagation from Singleton EJB to Stateless Session Bean
我有这个 EJB 单例 (EJB 3.1):
@Singleton
@Startup
@Lock(LockType.READ)
public class SingletonExample {
@EJB
private StatelessSBExample stlsb;
...
@Schedule(..........., persistent = false)
@AccessTimeout(0)
@Lock(LockType.READ)
public void call1SB() {
stlsb.doSomething();
}
@Schedule(..........., persistent = false)
@AccessTimeout(0)
@Lock(LockType.READ)
public void call2SB() {
stlsb.doSomething();
}
}
我的 bean 是传统的 EJB 无状态会话 Bean:
@Stateless
public class StatelessSBExample {
public void domSomething() {
...
}
}
用visualvm监控,发现有些线程在堆积。该应用程序从 Thread Live Peak = 92 开始,现在是 102。而且还在增加。在 VisualVM 线程中,我有几个状态为 "Park" 和 "Wait" 的线程。
在我的线程转储中,我有很多:
"Thread-42" - Thread t@190
java.lang.Thread.State: WAITING
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <71bfce05> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1088)
at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Locked ownable synchronizers:
- None
和
"__ejb-thread-pool13" - Thread t@130
java.lang.Thread.State: WAITING
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <5cfe398e> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Locked ownable synchronizers:
- None
我错在哪里?我只想执行 call1SB(),如果是 运行,则不再执行此方法(与 call2SB 相同)
P.S。我不能使用 LockType.WRITE 因为我想同时执行 call1SB() 和 call2SB() (我的 Singleton 中没有属性……只有方法)
默认的 EJB 锁定机制适用于常见的用例,但它们不是很灵活。在这种情况下,我建议使用您自己的锁定机制,如下所示:
private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
public void call1SB() {
if(lock.writeLock().tryLock()) {
// Acquires the write lock only if it
// is not held by another thread at the time of invocation.
stlsb.doSomething();
} // else { return; } // do nothing if already locked
}
与第二个 Singleton 方法的第二个锁相同。
我有这个 EJB 单例 (EJB 3.1):
@Singleton
@Startup
@Lock(LockType.READ)
public class SingletonExample {
@EJB
private StatelessSBExample stlsb;
...
@Schedule(..........., persistent = false)
@AccessTimeout(0)
@Lock(LockType.READ)
public void call1SB() {
stlsb.doSomething();
}
@Schedule(..........., persistent = false)
@AccessTimeout(0)
@Lock(LockType.READ)
public void call2SB() {
stlsb.doSomething();
}
}
我的 bean 是传统的 EJB 无状态会话 Bean:
@Stateless
public class StatelessSBExample {
public void domSomething() {
...
}
}
用visualvm监控,发现有些线程在堆积。该应用程序从 Thread Live Peak = 92 开始,现在是 102。而且还在增加。在 VisualVM 线程中,我有几个状态为 "Park" 和 "Wait" 的线程。 在我的线程转储中,我有很多:
"Thread-42" - Thread t@190
java.lang.Thread.State: WAITING
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <71bfce05> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1088)
at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Locked ownable synchronizers:
- None
和
"__ejb-thread-pool13" - Thread t@130
java.lang.Thread.State: WAITING
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <5cfe398e> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Locked ownable synchronizers:
- None
我错在哪里?我只想执行 call1SB(),如果是 运行,则不再执行此方法(与 call2SB 相同)
P.S。我不能使用 LockType.WRITE 因为我想同时执行 call1SB() 和 call2SB() (我的 Singleton 中没有属性……只有方法)
默认的 EJB 锁定机制适用于常见的用例,但它们不是很灵活。在这种情况下,我建议使用您自己的锁定机制,如下所示:
private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
public void call1SB() {
if(lock.writeLock().tryLock()) {
// Acquires the write lock only if it
// is not held by another thread at the time of invocation.
stlsb.doSomething();
} // else { return; } // do nothing if already locked
}
与第二个 Singleton 方法的第二个锁相同。