2011-05-25 75 views
1

我正在使用鑑別器登錄不同的文件。基於線程名稱。它通常提供良好的結果,但不包括那些與諸如名稱文件中的所有記錄儀的石英工作:我怎樣才能找到一個線程在java中運行的Quartz作業?

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

我想有一個文件,這是石英作業的名稱(基於它的東西)能夠快速找到哪個文件包含作業的日誌。如果當前的線程與工作相關聯,請問石英有問題嗎?

感謝

回答

1

最後,我用SLF4J手動表明MDC

在任務開始解決這個問題,我做

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

,並在年底

} 
    finally { 
     MDC.remove(MDC_KEY); 
    } 

所以我只需要檢查MDC中的密鑰以瞭解我是否在任務內。

+0

MDC是一個很好的解決方案。謝謝。 – happyyangyuan 2015-06-01 06:35:50

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"; 
    } 

} 
+0

如果我爲Thread和MessageFormat添加靜態導入,編譯如下: 'import static java.lang.Thread。*'and 'import static java.text.MessageFormat。*' – jerryb 2016-09-20 07:41:21

1

亞歷山大·帕夫洛夫的答案適合我(雖然我調整它使它成爲一個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」!