2014-09-25 71 views
-2

我使用Quarts Scheduler進行作業調度。我有各種各樣的工作,每天獲取不同用戶的醫療報告,並將該報告發送給個人用戶。每個作業都有一個與之相關的特定用戶。 在每個作業開始執行其業務邏輯之前,JobListener實現類將創建UserJobExecution類的一個實例。兩個線程之間的上下文切換問題

public class UserJobExecution 
{ 
    static ThreadLocal currentExecution = new ThreadLocal() 
    User user; 
    static UserJobExecution getCurrent(){ 
    (UserJobExecution) currentExecution.get(); 
    } 
    UserJobExecution(String jobName){ 
    try 
    { 
     user = getUserFromDB(jobName); 
    } 
    catch(e) 
    { 
     e.printStackTrace(); 
    } 
    } 
    User getUser(){ 
     return user; 
    } 
    //rest of the code 
} 

class WebServiceUtil{ 
    static HttpClient client = new HttpClient(new MultiThreadedHttpConnectionManager()); 
    User user; 
    WebServiceUtil(User user){ 
    this.user = user; 
    } 
    static WebServiceUtil getDefaultWs(){ 
    UserJobExecution userJobExecution = UserJobExecution.getCurrent(); 
    return (new WebServiceUtil(userJobExecution.getUser())); 
    } 
    static execute(String request){ 
    getDefaultWs().executeService(request); 
    } 

} 

上述兩個類都有一個User對象,它具有兩個字段username和password。 每個工作通過調用其自身的用戶名和密碼的executeMethod來獲取與特定用戶關聯的醫療報告,從而調用常用的Web服務。 Web服務需要時間來處理報告。因此,首先一份工作請求報告並獲取報告ID,然後該工作不斷調用Web服務,以每15秒檢索一次該報告,直到Web服務處理報告並獲取報告。

我面臨的問題是,如果有多個作業同時觸發,則它攪亂了用戶名和密碼。(以上getCurrent()方法被調用來獲得當前正在執行的任務)

我爲每個作業創建一個UserJobExecution實例。調度程序在每個作業執行之前調用jobToBeExecuted方法。

public class ExecutionJobListener implements JobListener { 
    public void jobToBeExecuted(JobExecutionContext context){ 
    //Other code 
    UserJobExecution userJobExecution = new UserJobExecution(job) 
    userJobExecution.save() 
    } 
//Rest of the code 
} 

回答

0

您似乎對所有作業都使用UserJobExecution的單個實例,這導致了經典的同步問題。由於所有作業在同一個UserJobExecution實例中使用相同的User屬性,因此多個作業可以同時調用getUserFromDB(),並且用戶屬性將被覆蓋。

嘗試構建您的類,以便所有作業不使用getUserFromDB()的結果使用作業間共享的引用(例如,爲每個作業使用單獨的引用,例如通過將其保留爲本地變量)。

+0

嗨Personne3000 ...我正在爲每個工作創建UserJobExecution的單個實例..我已編輯的問題在最後添加了代碼.. – 2014-09-26 08:57:21

+0

好的,你能解釋你如何使用你的getDefaultWs()靜態方法,以及getCurrent()方法?他們每次都使用相同的UserJobExecution實例,這就是爲什麼我認爲你只使用一個。 – personne3000 2014-09-29 08:49:04

0

從你的問題來看,使用Quartz Scheduler調度的方法並不完全清楚。不過,我認爲錯誤來自使用ThreadLocal與調度程序結合使用。 Quartz Scheduler使用內部線程池來運行作業。當作業被調用時,你不能確定它從哪個線程被調用。它可以是同一個線程或任何其他線程。考慮使用JobDataMap來存儲作業狀態。