[英]my application keeps receiving “Unfortunately ”My App“ has stopped” after Running the app
[英]Thread keeps running even after application has been stopped in Websphere
我有一个长期运行的线程,该线程是使用org.springframework.scheduling.commonj.WorkManagerTaskExecutor
和Spring创建的,并且正在Websphere Application Server 8中运行。
问题在于,即使应用程序已停止,该线程仍保持运行。 该线程也需要停止,但是没有发生。 我什至尝试使用Thread.currentThread().isInterrupted()
来检查当前线程是否被中断,但始终返回false
。 因此,无法通过我的代码知道线程是否应继续运行或停止。
这是我对WorkManagerTaskExecutor的春季配置:
<bean id="taskExecutor" class="org.springframework.scheduling.commonj.WorkManagerTaskExecutor">
<property name="workManagerName" value="wm/default" />
</bean>
线程是通过这种方式执行的:
Thread t = new EmailReaderThread(email);
workManagerTaskExecutor.execute(t);
我认为这不被视为非托管线程,因为我正在使用适当的WorkManager注册该线程,该容器由JNDI作为资源公开。
更新:这是创建线程的代码。
@Service
@Transactional
public class SmsServiceHypermedia implements SmsService {
@Autowired
private WorkManagerTaskExecutor workManagerTaskExecutor;
public SmsServiceHypermedia() {
createEmailReaderThread();
}
private void createEmailReaderThread() {
log.debug("Generating Email Reader Threads...");
Email email = getDefaultEmail(); //obtain the default Email object, not important for the problem.
EmailReaderThread r = new EmailReaderThread(email);
workManagerTaskExecutor.execute(r);
}
private class EmailReaderThread extends Thread {
private Email email;
private Session session;
public EmailReaderThread(Email email) {
this.email = email;
}
@Override
public void run() {
readEmails();
}
public void readEmails() {
final long delay = 30 * 1000; //delay between message poll.
log.debug("Starting to read emails for email: " + email.getAddress());
while(!Thread.currentThread().isInterrupted()) {
try {
log.debug("Current session: " + session);
Store store = session.getStore();
log.debug("Connecting using session: " + session);
store.connect();
Folder inbox = store.getFolder("INBOX");
inbox.open(Folder.READ_WRITE);
javax.mail.Message[] messages = inbox.search(
new FlagTerm(new Flags(Flags.Flag.SEEN), false));
for (javax.mail.Message message : messages) {
//Do something with the message
}
inbox.close(true);
store.close();
block(delay);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
//I know this could be implemented by calling Thread.sleep() is just that I ran out of options so I also tried it this way.
private void block(long millis) {
final long endTime = System.currentTimeMillis() + millis;
log.debug("Blocking for this amount of time: " + millis + " ms");
while (System.currentTimeMillis() < endTime) {
}
log.debug("End of blocking.");
}
}
}
根据CommonJ规范,仅当WorkManager的isDaemon()方法返回true时,WorkManager才会尝试停止其执行。 非守护程序Works预计运行时间短,因此无需停止它们。
问题是默认情况下,Spring使用的Work实现的isDaemon()方法(实际上包装了Runnable)返回false。 您可以通过使Runnable实现SchedulingAwareRunnable来更改它。
但是,这还不够。 如果WorkManager决定停止工作,则它将调用Work#release(),工作本身有责任确保停止。 特别是,WorkManager不会尝试中断正在执行工作的线程(因为这不是停止线程的可靠方法)。 问题在于,Spring使用的Work实现对release()方法具有空的实现,因此您不能使用该功能。
总结:如果要使用Spring,确保执行停止的唯一方法是为此设计自己的机制。
注意,使用SchedulingAwareRunnable仍然很有趣,因为这样可以避免WebSphere的线程监视器生成的警告(关于挂起的线程)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.