2016-11-29 1 views
0

Ich habe dieses EJB Singleton (EJB 3.1):sperren Ausbreitung von Singleton EJB Stateless Session Bean

@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(); 
    } 
} 

My Bean ist eine tradicional EJB Stateless Session Bean:

@Stateless 
public class StatelessSBExample { 
    public void domSomething() { 
    ... 
    } 
} 

Monitoring mit VisualVM, Ich habe festgestellt, dass sich einige Threads ansammeln. Die Anwendung startete mit Thread Live Peak = 92 und ist jetzt 102. Und es wird immer größer. In VisualVM Threads habe ich mehrere Threads mit dem Status "Park" und "Wait". In meinem Thread-Dump habe ich eine Menge:

"Thread-42" - Thread [email protected] 
    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 

und

"__ejb-thread-pool13" - Thread [email protected] 
    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 

Wo ist meine Schuld? Ich möchte nur call1SB() ausführen und, wenn es ausgeführt wird, führt diese Methode nicht erneut aus (das gleiche zu call2SB)

P.S. Ich kann LockType.WRITE nicht verwenden, weil ich call1SB() und call2SB() zur gleichen Zeit ausführen möchte (ich habe keine Attribute in meinem Singleton .. nur Methoden)

Antwort

0

Die Standard-EJB-Sperrmechanismen funktionieren gut für gewöhnlich Anwendungsfälle, aber sie sind nicht sehr flexibel. In einem solchen Fall hier würde ich vorschlagen, Ihre eigenen Locking-Mechanismus wie folgt zu verwenden:

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 
} 

Gleiche mit einer zweiten Sperre für Ihre zweite Singleton-Methode.

Verwandte Themen