如何找到一个线程在java中运行的Quartz作业?

时间:2011-05-25 17:03:18

标签: java quartz-scheduler

我使用鉴别器登录不同的文件。基于线程名称。它通常会得到很好的结果,除了石英作业都是文件记录器,名称如下:

org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-1.登录

我希望有一个文件,即石英作业的名称(基于它的东西),以便能够快速找到包含作业日志的文件。如果当前线程与作业相关,有没有办法询问quartz?

由于

3 个答案:

答案 0 :(得分:1)

最后,我通过手动指示slf4j MDC来解决它

在任务开始时,我做

try {
    MDC.put(MDC_KEY, getTaskName());

并在最后

    }
    finally {
        MDC.remove(MDC_KEY);
    }

所以我只需要检查MDC中的密钥以了解我是否在任务中。

答案 1 :(得分:1)

您的方法意味着您必须更改所有作业类的代码(或从基础作业类继承)。但是,有一种替代方法可以兼容其代码无法更改的作业。

您可以创建在执行期间更改线程名称的作业侦听器(如下面的示例所示)或设置MDC(如您的示例所示)并通过Scheduler.addJobListener()注册或通过Spring进行配置。

public class RenameThreadWhenJobRunning extends JobListenerSupport {
    /**
     * Must provide two groups - for name and for number
     */
    private String parsingPattern = "^(.+)_Worker-(\\d+)$";

    /**
     * {0} - Original full name (e.q. XXX_Worker-NN)
     * {1} - XXX - original thread name
     * {2} - NN - original worker number
     * {3} - Job key (e.g. JobGroup.JobName)
     * {4} - Job group
     * {5} - Job name
     */
    private String format = "{5}-Qz{2}";

    public void setParsingPattern(String parsingPattern) {
        this.parsingPattern = parsingPattern;
    }

    public void setFormat(String format) {
        this.format = format;
    }

    @Override
    public String getName() {
        return RenameThreadWhenJobRunning.class.getSimpleName();
    }

    @Override
    public void jobToBeExecuted(JobExecutionContext context) {
        final String originalThreadName = currentThread().getName();
        final Matcher matcher = Pattern.compile(parsingPattern).matcher(originalThreadName);
        if (matcher.matches()) {
            final JobKey key = context.getJobDetail().getKey();
            currentThread().setName(format(format,
                originalThreadName,
                matcher.group(1),
                matcher.group(2),
                key.toString(),
                key.getGroup(),
                key.getName()
            ));
            context.put(getOriginalThreadNameContextParameter(), originalThreadName);
        }
    }

    @Override
    public void jobWasExecuted(JobExecutionContext context, JobExecutionException jobException) {
        Object originalThreadName = context.get(getOriginalThreadNameContextParameter());
        if (originalThreadName instanceof String) {
            currentThread().setName((String)originalThreadName);
        }
    }

    String getOriginalThreadNameContextParameter() {
        return getName()+".originalThreadName";
    }

}

答案 2 :(得分:1)

Alexander Pavlov的回答对我有用(虽然我将其调整为Groovy文件)。我缺少的是将JobListener注册到调度程序。

我将Alexander的RenameThreadWhenJobRunning类的单例实例注册为bean'renameThreadJobListener'。 'quartzScheduler'bean已经存在于我的应用程序环境中。

由于我使用的是Grails,这里是我的resources.groovy中的块,可以移植到XML配置或基于注释的方法中:

quartzSchedulerInitializer(QuartzSchedulerInitializer) { bean ->
    bean.dependsOn = ['quartzScheduler', 'renameThreadJobListener'] as String[]
    quartzScheduler = ref('quartzScheduler')
    renameThreadJobListener = ref('renameThreadJobListener')
}

renameThreadJobListener(RenameThreadWhenJobRunning)

然后我创建了以下Groovy类:

import org.quartz.impl.matchers.EverythingMatcher
import org.springframework.beans.factory.InitializingBean

/**
 * At application startup, register job listeners on the QuartzScheduler bean.
 */
class QuartzSchedulerInitializer implements InitializingBean {

    def quartzScheduler
    def renameThreadJobListener

    @Override
    void afterPropertiesSet() throws Exception {
        def matcher = EverythingMatcher.allJobs()
        quartzScheduler.listenerManager.addJobListener(renameThreadJobListener, matcher)
    }
}

结果是我的工作线程名称现在看起来像“com.example.MyJob-Qz1”!