【问题标题】:Java / Wildfly: Threads piling up / Eclipse shows one additional running thread for each requestJava / Wildfly:线程堆积 / Eclipse 为每个请求显示一个额外的运行线程
【发布时间】:2026-01-07 21:00:02
【问题描述】:

我正在使用 javas Thread 通过 SMTP 连接到我们的邮件提供程序,因为这可能需要一些时间才能完成,我不希望请求等待。

但是看起来线程完成后并没有关闭。 我在 Eclipse 的调试模式下注意到了这一点:

每次我创建一个new Thread() 时,它都会添加一个正在运行的线程,但它并没有关闭它(至少我是这样认为的,因为eclipse 仍然显示Running)。

这是我的代码:

             Thread mailThread = new Thread() {

                    public void run() {

                        System.out.println("Does it work?");

                        try {
                            Transport t = session.getTransport("smtp");
                            t.connect("user","pass");
                            t.sendMessage(message,message.getAllRecipients());
                            t.close();
                            System.out.println("SENT");
                            return;
                        } catch (MessagingException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                            return;
                        }
                    }
                };

                mailThread.start();

这是否按预期工作?还是日食中的Running 有不同的含义?

【问题讨论】:

    标签: java eclipse multithreading wildfly threadpool


    【解决方案1】:

    我建议不要只用调试器来看看,看看你在某个时间点有哪些线程。调试器可能会显示在断点期间处于活动状态但在正常情况下不应该存在的线程。

    最好使用命令行工具jstack来创建线程转储。这将在某个时间点转储 JVM 中的所有线程。

    这里有一些关于如何使用它的说明:https://helpx.adobe.com/uk/experience-manager/kb/TakeThreadDump.html

    另一件事可以帮助您调试和查找转储中的线程:使用其中一个构造函数中的字符串为线程命名。

    new Thread("foo")
    

    然后在线程转储中找到这些就变得更容易了。

    如果您调用线程“foo”,那么它将显示在线程转储中,如下所示:

    "foo" #16 prio=5 os_prio=0 tid=0x0000000041970800 nid=0x41f8 waiting on condition [0x000000004244e000]
       java.lang.Thread.State: TIMED_WAITING (sleeping)
        at java.lang.Thread.sleep(java.base@9/Native Method)
        at *.ThreadReferenceTest$1.run(ThreadReferenceTest.java:14)
    
       Locked ownable synchronizers:
        - None
    
    "Service Thread" #15 daemon prio=9 os_prio=0 tid=0x0000000041914000 nid=0x3d90 runnable [0x0000000000000000]
       java.lang.Thread.State: RUNNABLE
    
       Locked ownable synchronizers:
        - None
    

    【讨论】:

    • 在使用 JavaEE 时,您不应该像这样手动生成新线程。如果你想做一些事情,比如在不阻塞的情况下发送电子邮件,请将消息发送到 jms 队列,并由发送电子邮件的人发送。然后,您可以轻松控制 smtp 会话的最大数量,并且如果您的电子邮件服务器出现故障,邮件可以在队列中等待重试。
    • 或者,只需将您的电子邮件发送到本地主机,然后让您的本地 mta 传送到您尝试发送到的服务器(智能主机)
    • @WillT:我同意你不应该在 JavaEE 中产生类似的线程。向本地主机发送电子邮件也是一个好主意。
    • 确实在催生一个新进程。 @WillT @gil.fernandes 我们正在实施排队系统,但这需要一些时间。我现在选择了一个 Promise 解决方案 CompletableFuture.supplyAsync(() -> this.send(session, message));。那解决了它。谢谢你们!