【问题标题】:java.util.concurrent.ExecutorService#submit taking a long timejava.util.concurrent.ExecutorService#submit 需要很长时间
【发布时间】:2018-01-01 01:43:35
【问题描述】:

我有一个非常奇怪的情况,我无法理解。我已经定义了一个线程池,它的用法是这样的

      ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5);
      ....some code.....
      logger.info("Event:{}, message:[{}]", Event.MESSAGE.name(), message);
      fixedThreadPool.submit(new Runnable() {
        @Override
        public void run() {
          ...some code...
        }
      });
      logger.info("Submitted: Event:{}, message:[{}]", Event.MESSAGE.name(), message);

现在这是我的日志消息输出

2017-07-25 20:44:41,020 [New I/O worker #1] XXXXXXXXX.XXXXXXXServiceImpl - Event:MESSAGE, message:[{"delegateTaskId":"_5ejQ7gtTXyfh6qnPrUeJg","sync":true,"accountId":"kmpySmUISimoRrJL6NL73w"}] 
2017-07-25 20:45:42,356 [New I/O worker #1] XXXXXXXXX.XXXXXXXServiceImpl - Submitted: Event:MESSAGE, message:[{"delegateTaskId":"_5ejQ7gtTXyfh6qnPrUeJg","sync":true,"accountId":"kmpySmUISimoRrJL6NL73w"}] 

查看两条消息的时间戳。虽然我希望提交到线程池队列应该是立即的,两条消息之间几乎需要一分钟。我试图消除所有的可能性,比如打印 GC 日志(没有暂停的主要 GC)、加载模式等。

当我看到这个时,系统上没有负载,CPU 使用率也很低。它在亚马逊 EC2 T2LARGE 盒子上运行,我可以看到 CPU 使用率并不高。

我阅读了 java 文档和谷歌,但找不到任何有用的东西。这是非常令人费解的。非常感谢任何指针。

--------编辑-----

我在日志消息中添加了时间,以确保没有日志记录问题。更新后的代码是

logger.info("Event:{}, time:{}, message:[{}]", Event.MESSAGE.name(), new Date(), message);
fixedThreadPool.submit(new Runnable() {
        @Override
        public void run() {
          ...some code...
        }
      });
logger.info("Submitted: Event:{}, time:{}, message:[{}]", Event.MESSAGE.name(), new Date(), message);

这是输出

Event:MESSAGE, time:Wed Jul 26 17:50:18 UTC 2017, message:[{"delegateTaskId":"pN7UzXfzSWajjJY33LbM1A","sync":true,"accountId":"kmpySmUISimoRrJL6NL73w"}] 
Submitted: Event:MESSAGE, time:Wed Jul 26 17:51:19 UTC 2017, message:[{"delegateTaskId":"pN7UzXfzSWajjJY33LbM1A","sync":true,"accountId":"kmpySmUISimoRrJL6NL73w"}]

可以看到,在线程池中提交任务所花费的时间几乎是一分钟

【问题讨论】:

  • 时间戳由记录器创建,看起来像是在线程本身中运行。可能会有一些同步或 io 延迟。您可以在消息本身中添加时间戳吗?
  • 从上面的描述看不清楚问题的确切原因,您可以使用分析器检查是否有任何线索。
  • 您在上面显示的第一条记录消息与您的线程的run 调用中的日志消息之间的时间差是多少?
  • 导致速度变慢的代码未在您的问题中显示。您需要添加其他代码,以便我们能够诊断您的问题。
  • @SeanBright 在第一条日志行和提交调用之间没有额外的代码

标签: java multithreading amazon-ec2 concurrency garbage-collection


【解决方案1】:

我已经在 AWS EC2 t2.large 实例上测试了以下代码:

import java.time.Instant;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class RaghvendraSinghTest
{
    public static void main(String[] args)
            throws Exception
    {
        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5);

        System.out.printf("[%s] Before fixedThreadPool.submit()%n", Instant.now());

        fixedThreadPool.submit(new Runnable() {
            @Override
            public void run()
            {
                System.out.printf("[%s] In run()%n", Instant.now());
            }
        });

        System.out.printf("[%s] After fixedThreadPool.submit()%n", Instant.now());

        fixedThreadPool.shutdown();
        fixedThreadPool.awaitTermination(30, TimeUnit.SECONDS);

        System.out.printf("[%s] After fixedThreadPool.shutdown()%n", Instant.now());
    }
}

运行代码会产生以下输出:

[2017-07-26T20:11:56.730Z] Before fixedThreadPool.submit()
[2017-07-26T20:11:56.803Z] After fixedThreadPool.submit()
[2017-07-26T20:11:56.803Z] In run()
[2017-07-26T20:11:56.804Z] After fixedThreadPool.shutdown()

这表明程序的整个运行时间不到 75 毫秒。关于您的问题,让我印象深刻的一件事是您的线程名称 - “New I/O worker #1” - 这向我表明这里有多个ExecutorServices 在起作用。

如果您运行我包含的代码 - 并且只是我包含的代码 - 您会看到与我的相似的结果吗?如果你这样做(我怀疑你会这样做),你应该包含足够的代码,以便我们可以复制你的问题。否则,这显然是特定于您的环境的。

【讨论】:

    【解决方案2】:

    我发现了这个问题。我们的 logback.xml 中有以下内容

    <appender name="SYSLOG-TLS" class="software.wings.logging.CloudBeesSyslogAppender">
        <layout class="ch.qos.logback.classic.PatternLayout">
            <pattern>%date{ISO8601} %boldGreen(${process_id}) %boldCyan(${version}) %green([%thread]) %highlight(%-5level) %cyan(%logger) - %msg %n</pattern>
        </layout>
    
        <host>XXXXXXXX</host>
        <port>XXXXXXXX</port>
        <programName>XXXXXXXXX</programName>
        <key>XXXXXXXXXXX</key>
        <threshold>TRACE</threshold>
    </appender>
    

    此配置使 logger.info 调用将日志发布到 logdna 和我们的系统配置方式,将日志发布到 logdna 服务器是同步的,有时需要长达 60 秒,我们的任务超时。

    现在需要弄清楚为什么这些 logdna 日志发布调用是同步的。

    【讨论】:

      猜你喜欢
      • 2013-09-07
      • 2020-08-26
      • 2014-10-09
      • 2012-11-26
      • 2019-12-27
      • 2017-10-22
      • 2020-11-15
      • 2016-05-19
      • 2011-11-20
      相关资源
      最近更新 更多