两个线程之间的上下文切换问题

时间:2014-09-25 14:31:30

标签: java multithreading thread-safety quartz-scheduler

我正在使用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秒检索一次报告,直到webservice处理报告并且作业获得报告。

我面临的问题是,如果同时触发多个作业,则会混淆用户名和密码。(调用上面的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
}

2 个答案:

答案 0 :(得分:0)

您似乎正在为所有作业使用UserJobExecution的单个实例,这会导致经典的同步问题。由于所有作业在同一个UserJobExecution实例中使用相同的User属性,因此多个作业可以同时调用getUserFromDB(),并且将覆盖用户属性。

尝试构建您的类,以便所有作业不使用作业之间共享的引用来存储getUserFromDB()的结果(例如,为每个作业使用单独的引用,例如将其保留为局部变量)。 p>

答案 1 :(得分:0)

您的问题并不完全清楚使用Quartz Scheduler安排了什么方法。尽管如此,我认为错误来自于将ThreadLocal与调度程序结合使用。 Quartz Scheduler使用内部线程池来运行作业。调用作业时,您无法确定从哪个线程调用它。它可以是相同的线程或任何其他线程。考虑使用JobDataMap存储作业状态。