您的位置:首页 > 运维架构 > Apache

Apache Email 遇到的线程释放慢问题

2016-01-07 20:02 716 查看
在实习中,需要做一个系统的发送邮件功能,因为是群发,需要发送给公司1500多人,因为是建立公告后,判断公告的重要性,重要则发送群邮,因此不能通过同步来实现,只能通过异步发送,一封邮件同时发给1500个人是不太现实的,所以开始的时候,将每封邮件发送给200个人,通过多线程并发,启动8个线程发送这8封邮件。如下代码:

private static ExecutorService executorService = Executors.newFixedThreadPool(3);

//发6封邮件,一封200个人
@org.junit.Test
public void test01() throws Exception {
//获取数据库内容
final HtmlEmail email = new HtmlEmail();
email.setSocketTimeout(30000);
email.setSocketConnectionTimeout(30000);
email.setCharset("UTF-8");
email.setHostName("smtp.xxxx.com");
email.setSmtpPort(25);
//设置发送人
email.setFrom("111@qq.com", "111");
email.setAuthentication("111@qq.com", "xxx");
email.setSubject("主题");
email.setMsg("内容");

//循环6次、发送6封邮件,每封邮件发200人
for (int k = 0; k < 6; k++) {
for (int i = 0; i < 200; i++) {
email.addTo("222@qq.com", "222");
}
executorService.execute(new Runnable() {
@Override
public void run() {
try {
email.send();
} catch (EmailException e) {
e.printStackTrace();
}
}
});
}
//将邮件信息插入数据库
}

    查看线程栈可以发现,线程一直是Runnable状态,如下代码:

"pool-2-thread-2@20561" prio=5 tid=0x86f nid=NA runnable
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(SocketInputStream.java:-1)
at java.net.SocketInputStream.read(SocketInputStream.java:129)
at com.sun.mail.util.TraceInputStream.read(TraceInputStream.java:79)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:218)
at java.io.BufferedInputStream.read(BufferedInputStream.java:237)
- locked <0x52e4> (a java.io.BufferedInputStream)
at com.sun.mail.util.LineInputStream.readLine(LineInputStream.java:57)
at com.sun.mail.smtp.SMTPTransport.readServerResponse(SMTPTransport.java:1070)
at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:986)
at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:197)
at javax.mail.Service.connect(Service.java:274)
at javax.mail.Service.connect(Service.java:91)
at javax.mail.Service.connect(Service.java:76)
at com.sun.mail.smtp.SMTPTransport.connect(SMTPTransport.java:104)
- locked <0x52e5> (a com.sun.mail.smtp.SMTPTransport)
at javax.mail.Transport.send(Transport.java:94)
at javax.mail.Transport.send(Transport.java:48)
at org.apache.commons.mail.Email.sendMimeMessage(Email.java:1411)
at org.apache.commons.mail.Email.send(Email.java:1448)
......
......
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)

    线程一直是Runnable状态持续10几分钟,折腾了很长时间没有发现出问题,期间有怀疑过是否是Hibernate的缓存导致邮件发送的时间延迟,后来无意中测试了,发送6封邮件,每封发一个人,如下代码:

//发6封邮件,每封发1个人
@org.junit.Test
public void test02() throws Exception {
final HtmlEmail email = new HtmlEmail();
email.setSocketTimeout(30000);
email.setSocketConnectionTimeout(30000);
email.setCharset("UTF-8");
email.setHostName("smtp.xxxx.com");
email.setSmtpPort(25);
//设置发送人
email.setFrom("111@qq.com", "111");
email.setAuthentication("111@qq.com", "xxx");
email.setSubject("主题");
email.setMsg("内容");

//循环6次、发送6封邮件,每封邮件发200人
for (int k = 0; k < 6; k++) {
email.addTo("222@qq.com", "222");
executorService.execute(new Runnable() {
@Override
public void run() {
try {
email.send();
} catch (EmailException e) {
e.printStackTrace();
}
}
});
}
//将邮件信息插入数据库
}


    这时,邮件发送很快,等待时间基本看不到,才发觉,猫腻藏在邮件发送的人数上。
    猜测:一封邮件发送200个人的时候,线程启动后,一直在Runnable,可能是一封邮件发送给200个人,邮件服务器应付不回来,只能慢慢运行、发送邮件,直到200封邮件发送出去后,线程才释放资源。
    后来才将代码改为一封一封的发送,一次群发的速度,很大一部分取决于邮件服务器。在线程池限制在20个前提下,发了1500封邮件差不多要1个小时。。。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: