我正在使用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
}
答案 0 :(得分:0)
您似乎正在为所有作业使用UserJobExecution的单个实例,这会导致经典的同步问题。由于所有作业在同一个UserJobExecution实例中使用相同的User属性,因此多个作业可以同时调用getUserFromDB(),并且将覆盖用户属性。
尝试构建您的类,以便所有作业不使用作业之间共享的引用来存储getUserFromDB()的结果(例如,为每个作业使用单独的引用,例如将其保留为局部变量)。 p>
答案 1 :(得分:0)
您的问题并不完全清楚使用Quartz Scheduler安排了什么方法。尽管如此,我认为错误来自于将ThreadLocal与调度程序结合使用。 Quartz Scheduler使用内部线程池来运行作业。调用作业时,您无法确定从哪个线程调用它。它可以是相同的线程或任何其他线程。考虑使用JobDataMap存储作业状态。