多线程Java newFixedThreadPool解释
我正在尝试诊断使用WSO2身份管理时遇到的问题
package org.wso2.carbon.identity.mgt;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* email sender this creates a new task in thread pool for each email sending request
*/
public class NotificationSender {
private static ExecutorService threadPool = Executors.newFixedThreadPool(5);
NotificationSendingModule module;
/**
* creates and submits a task to the thread pool
*
* @param module email sending module as task
*/
public void sendNotification(NotificationSendingModule module) {
threadPool.submit(module);
}
public NotificationSendingModule getModule() {
return module;
}
}
我正在对用户创建过程进行负载测试,在WSO2发送用户凭据配置邮件时,它正在向相同的电子邮件地址发送多封邮件,即使它们是唯一的
我从未使用过Java,但熟悉C#,因此能够毫无疑问地通读代码,我的问题是:
在Java文档中,它提到“如果一个线程在执行期间和关闭之前由于失败而终止,那么将创建一个新线程来代替它。”
这是否意味着如果电子邮件发送遇到错误,那么新线程将再次开始该过程
我想可能是发送电子邮件出错了,所以创建了一个新线程,但是日志记录没有绑定到结果中
还有,不打电话可以吗
threadPool.shutdown()
# 1 楼答案
当作为线程池一部分的线程抛出异常时,它确实会被新的新线程替换。但是,它不会重试相同的操作。只有在需要执行更多任务时,线程池才能继续执行其工作,才会进行替换
通常情况下,当线程以这种方式终止时,会记录堆栈跟踪,但异常可能会在某个地方被吞没。您可以尝试在发送代码周围添加try-catch块,并显式记录任何异常,以进一步分析问题
不调用
shutdown
是可以的# 2 楼答案
当我听到Java框架/应用程序服务器执行身份管理+线程池+奇怪的行为时,我立刻想到的是,大多数框架使用每用户线程模型(即:用户身份绑定到线程。如果切换线程,用户身份验证数据将丢失)。现在我不知道SO2的情况是否如此,但请参阅文档。这是“通常的怀疑”:线程本地身份验证机制无处不在
否。这意味着将创建一个新线程来处理其他提交的工作单元。但不会再次尝试失败的工作单元。就线程池而言,任务已经完成(有一个异常),并且已经完成了
事实并非如此。您应该使
NotificationSender
类具有某种类型的close()
或end()
方法。或者可以将它与一些WSO2生命周期回调联系起来(例如,在servlet上下文中,您有生命周期事件的侦听器,在Spring容器中,您有其他创建/销毁回调,…在您的上下文中工作的任何东西)。关闭线程池失败意味着某些线程将挂起,并且它们的资源永远不会释放。现在的线很便宜,但从长远来看,它们仍然会堆积起来,咬你一口。如果您确信在整个应用程序中只创建了一个NotificationSender
,并且该对象的生命周期与应用程序相同,那么它可能是类的ok。然后,从本质上说,关闭它与关闭应用程序是一样的,因此没有什么不好的事情发生