【问题标题】:Lock propagation from Singleton EJB to Stateless Session Bean从 Singleton EJB 到 Stateless Session Bean 的锁传播
【发布时间】:2017-04-13 20:27:04
【问题描述】:

我有这个 EJB Singleton (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 Threads 中,我有几个状态为“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 相同)

附:我不能使用 LockType.WRITE,因为我想同时执行 call1SB() 和 call2SB()(我的 Singleton 中没有属性.. 只有方法)

【问题讨论】:

    标签: java multithreading jakarta-ee threadpool ejb-3.1


    【解决方案1】:

    默认的 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 方法的第二个锁相同。

    【讨论】:

    • ReentrantReadWriteLock 需要是静态的吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多