Wie man einen Thread erstellen, die die ganze Zeit läuft meine Anwendung läuft
-
05-07-2019 - |
Frage
EDIT:
Ich bin jetzt sicher, dass das Problem der Beziehung steht
while (true)
Schleife alle anderen Befehle halten, wie ich es kommentiert habe und die Anwendung setzt, ohne die beigefügten Ausnahme. Ich bin nicht sicher, wie viel es ist wichtig, aber meine ServletContextListener
Implementierung sieht wie folgt aus:
public class BidPushService implements ServletContextListener{
public void contextInitialized(ServletContextEvent sce) {
//Some init code not relevant, omitted for clarity
BidPushThread t= new BidPushThread();
t.setServletContext(sce.getServletContext());
t.run();
}
So, jetzt der Thread ausgeführt wird, wenn die Anwendung bereitgestellt wird, sondern weil die while
Schleife kommentiert wird es hat keine wirkliche Bedeutung.
Ich brauche einen Thread im Hintergrund laufen zu lassen, wenn meine Anwendung geladen und ständig (ohne Timeout) eine bestimmte Warteschlange für Objekte überprüfen. Natürlich, wenn es Gegenstände gibt, es „kümmert sich um sie“ und geht dann in die Warteschlange zu überprüfen.
Derzeit bin ich der Umsetzung der ServletContextListener
Schnittstelle und ich werden, wenn die App Lasten genannt. Darin ich habe ein paar Dinge Wartung und einen Thread starten, die ich von java.lang.Thread
geerbt.
Hier ist, wo mein Problem beginnt (oder so glaube ich). In meiner run()
Methode, ich habe ein
while (true) {
//some code which doesn't put the thread to sleep ever
}
Wenn ich versuche, meine App an den Server zu implementieren erhalte ich eine java.util.concurrent.TimeOutException
.
Was mache ich falsch?
Kann ich nicht ein Gewinde, das immer läuft? Wenn der App entfernt wird, dass Faden durch das entsprechende Ereignis in meinem ServletContextListener
gestoppt wird.
ich wirklich etwas tun müssen, die auf die Überprüfung der Warteschlange ohne Verzögerung hält.
Vielen Dank für jede Hilfe!
Edit: Dies ist der Stack-Trace
GlassFish: deploy is failing=
java.util.concurrent.TimeoutException
at java.util.concurrent.FutureTask$Sync.innerGet(Unknown Source)
at java.util.concurrent.FutureTask.get(Unknown Source)
at com.sun.enterprise.jst.server.sunappsrv.SunAppServerBehaviour.publishDeployedDirectory(SunAppServerBehaviour.java:710)
at com.sun.enterprise.jst.server.sunappsrv.SunAppServerBehaviour.publishModuleForGlassFishV3(SunAppServerBehaviour.java:569)
at com.sun.enterprise.jst.server.sunappsrv.SunAppServerBehaviour.publishModule(SunAppServerBehaviour.java:266)
at org.eclipse.wst.server.core.model.ServerBehaviourDelegate.publishModule(ServerBehaviourDelegate.java:948)
at org.eclipse.wst.server.core.model.ServerBehaviourDelegate.publishModules(ServerBehaviourDelegate.java:1038)
at org.eclipse.wst.server.core.model.ServerBehaviourDelegate.publish(ServerBehaviourDelegate.java:872)
at org.eclipse.wst.server.core.model.ServerBehaviourDelegate.publish(ServerBehaviourDelegate.java:708)
at org.eclipse.wst.server.core.internal.Server.publishImpl(Server.java:2690)
at org.eclipse.wst.server.core.internal.Server$PublishJob.run(Server.java:272)
at org.eclipse.core.internal.jobs.Worker.run(Worker.java:55)
Mein Code:
public class BidPushThread extends Thread {
private ServletContext sc=null;
@Override
public void run() {
if (sc!=null){
final Map<String, List<AsyncContext>> aucWatchers = (Map<String, List<AsyncContext>>) sc.getAttribute("aucWatchers");
BlockingQueue<Bid> aucBids = (BlockingQueue<Bid>) sc.getAttribute("aucBids");
Executor bidExecutor = Executors.newCachedThreadPool();
final Executor watcherExecutor = Executors.newCachedThreadPool();
while(true)
{
try // There are unpublished new bid events.
{
final Bid bid = aucBids.take();
bidExecutor.execute(new Runnable(){
public void run() {
List<AsyncContext> watchers = aucWatchers.get(bid.getAuctionId());
for(final AsyncContext aCtx : watchers)
{
watcherExecutor.execute(new Runnable(){
public void run() {
// publish a new bid event to a watcher
try {
aCtx.getResponse().getWriter().print("A new bid on the item was placed. The current price "+bid.getBid()+" , next bid price is "+(bid.getBid()+1));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
};
});
}
}
});
} catch(InterruptedException e){}
}
}
}
public void setServletContext(ServletContext sc){
this.sc=sc;
}
}
Sorry für die Formatierung Chaos, sondern für das Leben meines „indent Code von 4 Leerzeichen“ funktioniert einfach nicht für mich Edit: Lesen Sie mehr über ‚Blocking‘ und umgesetzt, aber ich bin immer noch genau die gleiche Ausnahme und Stack-Trace zu bekommen. geändert, um den oben genannten Code die Verwendung von ‚Blocking‘
widerzuspiegelnLösung
Ihr Code nicht einen neuen Thread startet, läuft die Schleife im selben Thread und das ist, warum Sie einen Timeout-Fehler bekommen, wenn im Einsatz.
Um einen Thread starten Sie den Start-Methode aufrufen müssen, nicht die run-Methode.
public void contextInitialized(ServletContextEvent sce) {
//Some init code not relevant, omitted for clarity
BidPushThread t= new BidPushThread();
t.setServletContext(sce.getServletContext());
t.start();// run();
}
Andere Tipps
Zusammenfassung:
- Marks dieses Thema entweder als Daemon-Thread oder ein Benutzer-Thread. Das Java Virtual Machine beendet, wenn die nur Threads laufen alle Daemon Threads.
- Diese Methode muss aufgerufen werden, bevor der Thread gestartet wird.
- Diese Methode ruft zuerst die Methode checkaccess dieses Threads
ohne Argumente. Dies kann dazu führen Werfen eines Security (im
aktuelle Thread).
Zusammenfassung: In vielen Fällen, was wir wirklich wollen, ist Hintergrund-Threads erstellen das tut einfach, periodische Aufgaben in einem Anwendung. Die setDaemon () Methode kann verwendet werden, um ein Thema als markieren Daemon-Thread, die getötet werden sollten, und verworfen, wenn keine andere Anwendungsthreads bleiben. Normalerweise, das Java-Interpreter läuft weiter bis alle Threads abgeschlossen haben. Aber Wenn Daemon-Threads sind die einzige noch am Leben Fäden, der Dolmetscher verlassen wird.
Dies wäre eine sehr schlechte Idee. Sie würden eine 100% CPU-Last, ohne einen guten Grund führen.
Die richtige Lösung ist wahrscheinlich, den Faden zu blockieren, wenn die Warteschlange leer ist. Dies ist trivialerweise mit einem BlockingQueue
implementiert.
Can't I have a thread which is always running? When the app is removed,
that thread is stopped by the corresponding event in my ServletContextListener.
„Das Gewinde wird gestoppt“? Wie? Es gibt keine Abbruchbedingung in Ihrer while (true) {...} Schleife. Wie werden Stoppen Sie es? Sind Sie mit dem Thread.stop () -Methode? Das ist unsicher und wurde als veraltet Weg zurück in Java 1.1
Wenn Sie setDaemon verwenden (true), wird der Thread aktiv bleiben, nachdem Sie die Web-App mit Ihrem App-Server-Management-Tools gestoppt haben. Dann, wenn Sie die Web-App neu starten, werden Sie einen anderen Thread bekommen. Selbst wenn Sie die Web-App deimplementieren versuchen, bleiben der Thread läuft und wird die gesamte Web-App ist Garbage Collection verhindern. Dann die nächste Version Umschichtung gibt Ihnen eine zusätzliche Kopie von allem, was im Speicher.
Wenn Sie eine Ausgangsbedingung für die Schleife (z.B. InterruptedException oder eine flüchtige „StopNow“ boolean), können Sie dieses Problem vermeiden.
Werfen Sie einen Blick auf java.langThread.setDaemon () -Methode, kann es das, was Sie benötigen