Quartz.net 多线程和线程安全
Quartz.net multithreading and thread safety
我最近开始使用quartz.net,我对线程安全有疑问。
public class QuartzService
{
public async Task Start()
{
// construct a scheduler factory
NameValueCollection props = new NameValueCollection
{
{ "quartz.serializer.type", "binary" }
};
StdSchedulerFactory factory = new StdSchedulerFactory(props);
// get a scheduler
IScheduler sched = await factory.GetScheduler();
// define the job and tie it to our HelloJob class
IJobDetail job = JobBuilder.Create<TestJob>().StoreDurably()
.WithIdentity("myJob", "jobGroup1")
.Build();
await sched.AddJob(job, true);
// Trigger the job to run now, and then every 40 seconds
ITrigger trigger1 = TriggerBuilder.Create()
.WithIdentity("myTrigger1", "group1")
.StartNow()
.WithSimpleSchedule(x => x
.WithIntervalInSeconds(5)
.RepeatForever())
.ForJob(job)
.Build();
// Trigger the job to run now, and then every 40 seconds
ITrigger trigger2 = TriggerBuilder.Create()
.WithIdentity("myTrigger2", "group1")
.StartNow()
.WithSimpleSchedule(x => x
.WithIntervalInSeconds(5)
.RepeatForever())
.ForJob(job)
.Build();
await sched.ScheduleJob(trigger1);
await sched.ScheduleJob(trigger2);
await sched.Start();
}
}
public class TestJob : IJob
{
public async Task Execute(IJobExecutionContext context)
{
await Console.Out.WriteLineAsync($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}");
}
}
在上面的例子中,我有一个有两个触发器的作业。我的问题是这两个触发器在 运行 时是否共享同一个作业实例?或者每次触发器 运行s 都会创建一个新的 IJobDetail 实例。我试图阅读 quartz.net 的文档,但它非常混乱,因为它将 JobDetail 实例与作业实例混合在一起,我不太清楚这里的情况。
使用默认作业工厂 SimpleJobFactory,为每个作业调用创建给定作业类型(CLR 类型)的新对象实例。默认情况下,CLR 意义上的作业对象实例永远不会被触发器共享。
但是,可以创建一个自定义作业工厂,它可以 return 单例,例如,控制反转容器。
作业类型也有区别。 JobDetails 描述了一种工作类型,多个触发器可以指向相同的细节(因此也指向相同的类型)。这导致如果作业没有应用 PreventConcurrentExecutionAttribute
,则可以同时存在 相同 CLR 类型 运行 的多个作业。为了让事情变得有趣,PreventConcurrentExecutionAttribute
适用于工作详细信息,因此两个不同的工作详细信息(不同的工作密钥)但相同类型可以再次 运行 同时。
我最近开始使用quartz.net,我对线程安全有疑问。
public class QuartzService
{
public async Task Start()
{
// construct a scheduler factory
NameValueCollection props = new NameValueCollection
{
{ "quartz.serializer.type", "binary" }
};
StdSchedulerFactory factory = new StdSchedulerFactory(props);
// get a scheduler
IScheduler sched = await factory.GetScheduler();
// define the job and tie it to our HelloJob class
IJobDetail job = JobBuilder.Create<TestJob>().StoreDurably()
.WithIdentity("myJob", "jobGroup1")
.Build();
await sched.AddJob(job, true);
// Trigger the job to run now, and then every 40 seconds
ITrigger trigger1 = TriggerBuilder.Create()
.WithIdentity("myTrigger1", "group1")
.StartNow()
.WithSimpleSchedule(x => x
.WithIntervalInSeconds(5)
.RepeatForever())
.ForJob(job)
.Build();
// Trigger the job to run now, and then every 40 seconds
ITrigger trigger2 = TriggerBuilder.Create()
.WithIdentity("myTrigger2", "group1")
.StartNow()
.WithSimpleSchedule(x => x
.WithIntervalInSeconds(5)
.RepeatForever())
.ForJob(job)
.Build();
await sched.ScheduleJob(trigger1);
await sched.ScheduleJob(trigger2);
await sched.Start();
}
}
public class TestJob : IJob
{
public async Task Execute(IJobExecutionContext context)
{
await Console.Out.WriteLineAsync($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}");
}
}
在上面的例子中,我有一个有两个触发器的作业。我的问题是这两个触发器在 运行 时是否共享同一个作业实例?或者每次触发器 运行s 都会创建一个新的 IJobDetail 实例。我试图阅读 quartz.net 的文档,但它非常混乱,因为它将 JobDetail 实例与作业实例混合在一起,我不太清楚这里的情况。
使用默认作业工厂 SimpleJobFactory,为每个作业调用创建给定作业类型(CLR 类型)的新对象实例。默认情况下,CLR 意义上的作业对象实例永远不会被触发器共享。
但是,可以创建一个自定义作业工厂,它可以 return 单例,例如,控制反转容器。
作业类型也有区别。 JobDetails 描述了一种工作类型,多个触发器可以指向相同的细节(因此也指向相同的类型)。这导致如果作业没有应用 PreventConcurrentExecutionAttribute
,则可以同时存在 相同 CLR 类型 运行 的多个作业。为了让事情变得有趣,PreventConcurrentExecutionAttribute
适用于工作详细信息,因此两个不同的工作详细信息(不同的工作密钥)但相同类型可以再次 运行 同时。