提问人:jllangston 提问时间:7/11/2023 更新时间:7/11/2023 访问量:89
无限循环的 Java 未知原因
Java unknown cause for infinite loop
问:
我有一个代码结果,我无法在发送电子邮件的 Java 11 代码中解释。
我正在使用javax邮件包:
import javax.mail.Message;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
代码如下:
Properties props = System.getProperties();
props.put("mail.smtp.host", smtpHost);
Session session = Session.getInstance(props);
int nMaxTries = 5;
int nTries = 0;
boolean success = false;
while (!success || nTries >= nMaxTries) {
try {
MimeMessage msg = new MimeMessage(session);
//set message headers
msg.addHeader("Content-type", "text/HTML; charset=UTF-8");
msg.addHeader("format", "flowed");
msg.addHeader("Content-Transfer-Encoding", "8bit");
msg.setFrom(new InternetAddress(fromEmail, from));
msg.setSubject(subject, "UTF-8");
msg.setContent(body, "text/html");
msg.setSentDate(new Date());
msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(toEmail, false));
System.out.println("Message is ready");
Transport.send(msg);
System.out.println("EMail Sent Successfully!!");
success = true;
} catch (Exception e) {
e.printStackTrace();
nTries++;
}
}
我注意到有时电子邮件会失败,因此重试。这使用将输出通过管道传递到日志的 cron 进程运行。这已经工作了几个星期。今天早上,我收到了近 400,000 封电子邮件。我在日志中一遍又一遍地看到这一点:
Message is ready
EMail Sent Successfully!!
Message is ready
EMail Sent Successfully!!
Message is ready
EMail Sent Successfully!!
Message is ready
EMail Sent Successfully!!
Message is ready
这是一个单线程进程。看到这里,我意识到我可以增加循环中的计数器,而不仅仅是 catch 语句,这样这些无限循环就会停止。谁能解释一下 while 循环如何无法完成的逻辑?
谢谢!
答:
错误出在 while 循环中。
您有两个条件。
第一个是“继续,而成功是”假的” 第二个是“当 nTries 等于或优于 nMaxTries 时继续”
现在,如果第一秒或第二秒是正确的(您使用了 ||),则将执行 while 指令中的代码。
我怀疑的是,电子邮件在未知的时间段内发送了 5 次失败(因此将变量 nTries 递增为 5)并导致循环,因为第二个条件始终为真。(nTries >= nMaxTries)。
为了纠正该问题,您需要执行以下测试:
!success && nTries < nMaxTries
评论
循环是错误的。它应该是这样的:while
while (!success && nTries < nMaxTries)
否则,两者都从 0 开始,并且无论增加多少次,条件始终为 true,并且如果邮件正确发送,操作员仍将考虑 和 为 true 之间的比较,即使为 false。nTries
nMaxTries
>=
nTries
||
nTries
nMaxTries
!success
让我们假设一个场景,在前 5 次中,发送消息失败(发生异常),因此您的变量现在等于 并且现在您已成功发送消息,因此,但您使用了 OR 条件,因此它将检查第二个条件是否为 true。所以总的来说,表达成为真的。由于此条件永远不会改变,而循环现在被卡住并已成为无限循环。nTries
nMaxTries
success=true
nTries >= nMaxTries
!success || nTries >= nMaxTries
如前所述,使用
!success && nTries < nMaxTries
但是,忘记测试成功布尔值,并在发送电子邮件时跳出循环。
while (nTries < nMaxTries) {
try {
MimeMessage msg = new MimeMessage(session);
//set message headers
msg.addHeader("Content-type", "text/HTML; charset=UTF-8");
msg.addHeader("format", "flowed");
msg.addHeader("Content-Transfer-Encoding", "8bit");
msg.setFrom(new InternetAddress(fromEmail, from));
msg.setSubject(subject, "UTF-8");
msg.setContent(body, "text/html");
msg.setSentDate(new Date());
msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(toEmail, false));
System.out.println("Message is ready");
Transport.send(msg);
System.out.println("EMail Sent Successfully!!");
success = true; // keep for final status
break; // terminate the loop here.
} catch (Exception e) {
e.printStackTrace();
nTries++;
}
}
评论
&& nTries < nMaxTries
!success || nTries >= nMaxTries
|| nTries >= nMaxTries