2014-11-24 62 views
0

我有一個Singleton會話Bean執行的後臺任務:EJB 3.1的Singleton會話Bean @PreDestroy方法不叫

@Singleton 
@ConcurrencyManagement(ConcurrencyManagementType.BEAN) 
@TransactionManagement(TransactionManagementType.BEAN) 
@Startup 
public class TaskQueue { 

private static final Logger LOGGER = Logger.getLogger("TaskQueue"); 

@Resource 
private SessionContext sessionContext; 

private final ArrayList<Runnable> tasks = new ArrayList<Runnable>(); 
private boolean running = false; 

@PostConstruct 
public void postConstruct() { 
    LOGGER.info("postConstruct"); 

    running = true; 
    sessionContext.getBusinessObject(TaskQueue.class).taskLoop(); 
} 

@PreDestroy 
public void preDestroy() { 
    LOGGER.info("preDestroy"); 
    running = false; 
    synchronized (tasks) { 
     tasks.notifyAll(); 
    } 
} 

public void addTask(Runnable r) { 
    synchronized (tasks) { 
     tasks.add(r); 
     tasks.notifyAll(); 
    } 
} 

@Asynchronous 
public void taskLoop() { 
    while (running) { 
     Runnable task; 
     synchronized (tasks) { 
      LOGGER.info("Fetching next task..."); 
      if (tasks.isEmpty()) { 
       try { 
        LOGGER.info("Task queue is empty. Waiting..."); 
        tasks.wait(); 
        LOGGER.info("Resumed"); 
        continue; 
       } catch (InterruptedException e) { 
        break; 
       } 
      } 

      task = tasks.remove(0); 
     } 

     LOGGER.info("Executing task..."); 
     task.run(); 
    } 

    running = false; 
    LOGGER.info("Task queue exited"); 
} 
} 

當我試圖阻止模塊,取消部署模塊,或者停止服務器,該preDestroy()方法沒有被調用,並且停止/取消部署過程將不會繼續。停止服務器的唯一方法是殺死Java進程。

我正在使用Jboss EAP 6.0。

我的代碼出了什麼問題?如何修復它,或者使用EJB 3.1做後臺任務隊列處理的另一種方法是什麼?

回答

1

首先,EE規範禁止管理自己的線程。你可以做到這一點,但你應該意識到你違反了規範並理解了所有的內在含義。相反,您應該考慮利用Managed Executor服務[1]。

這就是說我懷疑在這裏發生的事情是你的taskLoop鎖定訪問你的單身(包括預銷燬)的其他方法。默認情況下@Singleton的所有方法都是@Lock LockType.Write。既然你已經手動同步,你應該嘗試用標註@Lock(LockType.Read)你@Singleton類[2]

[1] https://docs.oracle.com/javaee/7/api/javax/enterprise/concurrent/ManagedExecutorService.html

[2] https://docs.oracle.com/javaee/6/api/javax/ejb/LockType.html

+0

不幸的是,我使用Java EE ** 6 **,其中'ManagedExecutorService'不可用。任何想法?順便說一下,因爲我一直在進行Bean Managed Concurrency,所以@Lock在這裏沒有必要。 – 2014-11-25 02:17:31

+0

我的問題的最終解決方案是升級到Java EE 7,並使用**單線程**'ExecutorService'和'ManagedThreadFactory'。 @NBW的建議讓我在那裏,並將其標記爲公認的答案。 – 2014-11-25 07:09:31

相關問題