2010-04-22 71 views
5

我創建了@Singleton,@Schedule和@Timeout註釋的簡單示例,以嘗試解決我的問題。ejb 3.1中的計時器服務 - 計劃調用超時問題

這種情況是這樣的:EJB每5秒鐘調用一次「檢查」函數,並且如果滿足某些條件,它將創建單個操作計時器,以異步方式調用一些長時間運行的進程。 (這是一種隊列實現類型的東西)。然後它繼續檢查,但是當長時間運行的過程在那裏時,它不會啓動另一個過程。

下面是我想到的代碼,但這種解決方案不起作用,因爲它看起來像我做的異步調用實際上是阻止我的@Schedule方法。

@Singleton 
@Startup 
public class GenerationQueue { 

    private Logger logger = Logger.getLogger(GenerationQueue.class.getName()); 

    private List<String> queue = new ArrayList<String>(); 

    private boolean available = true; 

    @Resource 
    TimerService timerService; 

    @Schedule(persistent=true, minute="*", second="*/5", hour="*") 
    public void checkQueueState() { 

     logger.log(Level.INFO,"Queue state check: "+available+" size: "+queue.size()+", "+new Date()); 

     if (available) { 

      timerService.createSingleActionTimer(new Date(), new TimerConfig(null, false)); 
     } 

    } 

    @Timeout 
    private void generateReport(Timer timer) { 

     logger.info("!!--timeout invoked here "+new Date()); 

     available = false; 

     try { 

      Thread.sleep(1000*60*2); // something that lasts for a bit 

     } catch (Exception e) {} 

     available = true; 

     logger.info("New report generation complete"); 

    } 

我在這裏錯過了什麼,或者我應該嘗試不同的方法?任何最受歡迎的想法:)

測試與Glassfish的3.0.1最新版本 - 忘了提

回答

11

默認@ConcurrencyManagement爲單身是ConcurrencyManagementType.CONTAINER與LockType.WRITE的默認@Lock。基本上,這意味着每個方法(包括generateReports)都有效地用synchronized關鍵字標記,這意味着checkRateState會在generateReport運行時阻塞。

考慮使用ConcurrencyManagement(ConcurrencyManagementType.BEAN)或@Lock(LockType.READ)。如果這兩個建議都沒有幫助,我懷疑你已經找到了一個Glassfish錯誤。

另一方面,您可能希望持久= false,因爲即使您的服務器處於脫機狀態,您可能也不需要保證checkQueueState方法每5秒觸發一次。換句話說,當您將服務器重新聯機時,您可能不需要容器來觸發「追趕」。

+0

非常感謝,問題是通過改變ConcurrencyManagementType.BEAN的協調性來解決的,是的,我會改變爲false :) 感謝您的幫助。 – Greg 2010-04-23 08:03:11

+1

不錯的答案,學到了新的東西。謝謝! – 2010-04-26 20:47:03