gpt4 book ai didi

java - 并发发送带附件的 HtmlEmail 和 "Too many open files"错误

转载 作者:行者123 更新时间:2023-12-02 10:56:16 25 4
gpt4 key购买 nike

我怀疑我使用了错误的 Apache Common Email 库来发送带有附件的电子邮件。有时我会收到“打开的文件太多”错误,如果我使用lsof检查打开的文件,我会发现附件文件被打开了多次:

图像1.png图片2.png图片1.png...

所以我怀疑我没有正确释放文件(或者没有关闭某些资源)。也可能该软件可以工作,但如果外部 SMTP 服务器发生故障(连接异常),我的代码不会释放一些资源。

来源:

/* Async Thread to send email */
Thread t = new Thread(){
@Override
public void run(){
try{
task(request,idNewsletter);
}
catch (Exception e){
log.error("Error " + e);
}
}
};
t.start();
[...]

任务方法:

    ExecutorService executor = Executors.newFixedThreadPool(10);
[...]

List<Future<Integer>> list = new ArrayList<Future<Integer>>();
for (int i = 0; i < dests.length; i++) {
HtmlEmail htmlEmail = getHtmlMail([...]);

ArrayList<InternetAddress> dest = new ArrayList<InternetAddress>();
InternetAddress add = new InternetAddress();
add.setAddress(dests[i]);
dest.add(add);

htmlEmail.setBcc(dest);
htmlEmail.setMailSession(getEmailSession());
htmlEmail.buildMimeMessage();

Callable<Integer> worker = new EmailService(htmlEmail,i);
Future<Integer> future = executor.submit(worker);
list.add(future);

}

try {
executor.shutdown();
executor.awaitTermination(28800, TimeUnit.SECONDS);
}
catch (InterruptedException e) {
log.error("Error=" + e);
}
finally {
if (!executor.isTerminated()) {
log.error("Task cancelled");
}
executor.shutdownNow();
}

getHtmlEmail 方法

private static URL image;
static {
image= (new File("somepath").toURI().toURL());
}


private HtmlEmail getHtmlMail([...]){

HtmlEmail htmlEmail = new HtmlEmail();

htmlEmail.setCharset("UTF-8");
htmlEmail.setSubject("someSubject");
htmlEmail.setFrom(from);
htmlEmail.setSentDate(new java.util.Date());
[...]
String cidImage= htmlEmail.embed(image, "Email image");
text= text.replace("cid:image", "cid:" + cidImage);

[...] /* Other attachments */

htmlEmail.setHtmlMsg(text);
return htmlEmail;

}

getEmailSession 方法

private Session getEmailSession() throws Exception{  
if (mailSession != null)
return mailSession;
else {
InitialContext ic = new InitialContext();
mailSession = (Session) ic.lookup("someJNDI");

mailSession.getProperties().put("mail.smtp.connectiontimeout", 1000);
mailSession.getProperties().put("mail.smtp.timeout", 5000);

return mailSession;
}

}

以及发送电子邮件的方法

@Override
public Integer call() throws Exception {
try{
htmlEmail.sendMimeMessage();
}
catch(Exception e){
log.error("Error=" + e);
htmlEmail=null;
return new Integer(0);
}
return new Integer(1);
}

有什么提示吗?

提前致谢安德里亚

最佳答案

我相信这就是问题所在:

static {
image= (new File("somepath").toURI().toURL());
}

它是静态。这是您遇到的并发问题。它总是在那里。这就是我认为正在发生的事情。假设它位于一个名为 Url 的类中,并且您有一个返回该值的非静态 getUrl() 。如果您这样做:

Url url1 = new Url();
Url url2 = new Url();
url1.getUrl();
url2.getUrl();

然后他们每个人都应该返回一个不同的 url 实例。但是,您将 url 属性初始化为 static,因此实际情况是Url 的所有实例都只有一个 url。 url 属性不属于每个对象,而仅属于类本身。因此,当您尝试调用它时,它们都会一次又一次地尝试访问该文件,因为它从来没有“创建”,也没有在每个实例中初始化。将其视为始终存在的东西,因为类本身拥有它,而不是实例,从而给您带来打开文件过多错误。

所以我建议你将其从静态中删除。也许你可以做这样的事情:

class Url{
private final URL url;
public Url() {
url= (new File("somepath").toURI().toURL());
}
}

然后只需在您想要的任何地方使用该 url 属性即可。

关于java - 并发发送带附件的 HtmlEmail 和 "Too many open files"错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51707078/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com