Thread läuft auch nach der Anwendung gestoppt wurde, die in Websphere
Habe ich einen lange Laufenden thread, die erstellt wird, mithilfe von org.springframework.scheduling.commonj.WorkManagerTaskExecutor
mit Feder und läuft auf Websphere Application Server 8.
Das problem ist, dass dieser thread weiter läuft, auch wenn die Anwendung beendet wurde. Der thread gestoppt werden muss auch, aber es ist nicht passiert. Ich habe sogar versucht zu verwenden Thread.currentThread().isInterrupted()
um zu überprüfen, ob der aktuelle thread unterbrochen wurde, aber es gibt immer false
. So gibt es keine Möglichkeit zu wissen, durch meinen code, wenn der Thread soll weiter laufen oder stoppen.
Dies ist mein spring-Konfiguration für die WorkManagerTaskExecutor:
<bean id="taskExecutor" class="org.springframework.scheduling.commonj.WorkManagerTaskExecutor">
<property name="workManagerName" value="wm/default" />
</bean>
Dem thread ausgeführt wird, auf diese Weise:
Thread t = new EmailReaderThread(email);
workManagerTaskExecutor.execute(t);
- Was bin ich?
- Was kann ich tun, damit wenn die Anwendung beendet die Anwendung den thread (die threads, die erstellt wurden, von der Anwendung) reagiert zu?
Ich denke, dies wird nicht als eine nicht verwaltete Threads, weil ich mich registrieren den thread mit den entsprechenden WorkManager, die den container stellt als eine Ressource über JNDI.
Update:
Hier ist der code, der erstellt den Thread.
@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.");
}
}
}
- Sollten Sie keine übergabe eines Runnable zu WorkManagerTaskExecutor.execute(WorkManagerTaskExecutor Aufgabe) statt eines Threads?
- Ein Thread implementiert Runnable, so ist ein Runnable. Ich denke, dass ist nicht das problem.
- Vollzieher nie rufen Sie die
start()
- Methode des übergebenen thread (nur dierun()
), so dass Sie könnte genauso gut verwenden ein normales runnable (nicht thread) - Ja, weil der, dass der ausgeführte code muss in der run () - Methode. Überprüfen Sie meine aktualisierten code.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Entsprechend der CommonJ specs, eine WorkManager werden versuchen, stoppen Sie die Ausführung einer Arbeit nur zu, wenn seine isDaemon () - Methode gibt true zurück. Non-daemon Arbeiten werden voraussichtlich kurz ausgeführt, so dass Sie nicht angehalten werden muss.
Das problem ist, dass standardmäßig die isDaemon () - Methode der Arbeit, die Implementierung von Spring (und die tatsächlich wickelt sich die Runnable) gibt false zurück. Sie können das ändern, indem Ihr das Runnable implementieren SchedulingAwareRunnable.
Aber das ist nicht genug. Wenn der WorkManager entscheidet, die Arbeit zu beenden, dann wird es Arbeit nennt#release() und es ist die Verantwortung, die Arbeit selbst zu machen sicher, dass es anhält. Insbesondere der WorkManager nicht versucht zu unterbrechen, den thread, der ist bei der Ausführung der Arbeiten (weil, dass ist kein verlässlicher Weg, um stop-thread). Das problem ist, dass die Arbeit, die Implementierung von Spring hat eine leere Implementierung für die release () - Methode, so dass Sie nicht verwenden können, die Funktion.
Zusammenfassen: wenn Sie möchten, nutzen Spring, der einzige Weg, um sicherzustellen, dass die Ausführung beendet wird, ist für die Gestaltung Ihres eigenen Mechanismus an.
Beachten Sie, dass es noch interessant, zu verwenden SchedulingAwareRunnable, denn dadurch vermeiden Sie die Warnungen generiert durch die WebSphere-thread monitor (über hängende threads).