【问题标题】:Does @Scheduler start a new thread?@Scheduler 是否启动一个新线程?
【发布时间】:2014-03-06 20:04:28
【问题描述】:

我有一个 Spring 应用程序,它有几个 scheduled 方法

在应用程序运行一段时间后,Lo4J 似乎停止滚动到新文件并增长到 10 GB。

所有配置看起来都很好,我只使用记事本++打开日志文件(意味着编辑器没有锁定日志文件)

所以我认为应用程序中可能有另一个线程正在运行。我记得当前应用程序中的任何多线程实现。

那么有没有可能是@Scheduled方法导致了这个问题呢?

【问题讨论】:

  • All configuration looks fine... 除非你给我们看,否则我们不知道;-P
  • @Scheduled 标记一个方法,以便 Spring 使用 ExecutorService 根据您的配置在单独的线程中执行该方法。我看不出它会如何影响日志记录。
  • 谢谢。日志配置问题是[stackoverflow.com/questions/21841549/…,在我修复编码后它仍然存在问题(在一个大文件中增长)
  • 我猜如果有多个线程在没有正确同步的情况下写入日志,那么如果两个线程写入同一个日志.....我猜这就是为什么会发生这种情况?

标签: java spring jakarta-ee log4j


【解决方案1】:

@Scheduled 导致代码在单独的线程中运行,不一定是新的,因为它可能来自线程池。

发生日志文件的非翻转是因为当 log4j 尝试重命名文件以进行翻转时,某些应用程序线程正在那个精确的时刻记录到该文件。

根据log4j滚动文件实现RollingFileAppender的代码,当滚动到时候(调用rollOver()方法),尝试重命名文件。

如果文件被锁定,则不会发生翻转,并且 log4j 继续使用同一个文件,直到下一次触发翻转策略并再次尝试重命名。

所以@Scheduled 注释可能对此有所贡献,但它可能不是唯一的责任,例如,如果它是一个 Web 应用程序等有大量请求。

要降低翻转失败的可能性,请尝试将 @Scheduled 线程更改为在与翻转尝试发生时不同的时刻运行。

同时将日志记录级别降低到ERROR 将降低翻转失败的可能性。另见How to find which thread is locking a file

【讨论】:

    【解决方案2】:

    它应该使用配置的线程池分配的线程之一。每次执行其中一个计划任务时都会选择该线程,一旦任务完成,该线程将被释放回池中。日志记录的数量取决于任务运行的频率以及您拥有多少日志语句。因此,除非有 大量 日志记录,否则这可能不是您的问题。

    您应该在调度程序配置中使用与此类似的内容来确定池大小。您的池大小还应由您机器上的可用线程决定。核心数、每核心线程数、jvm等。

    <task:annotation-driven scheduler="taskScheduler"/>
    <task:scheduler id="taskScheduler" pool-size="2"/>
    

    【讨论】:

      猜你喜欢
      • 2014-03-19
      • 2012-02-28
      • 1970-01-01
      • 2019-04-08
      • 2011-07-20
      • 2012-05-06
      • 1970-01-01
      • 1970-01-01
      • 2014-07-15
      相关资源
      最近更新 更多