2016-08-10 3 views
0

Ich habe eine Situation, wo ich eine Aufgabe starten muss, die für 4 Stunden läuft. Ich benutze Servlet, um den Prozess zu starten. Allerdings erhalte ich eine Speicherleck-Ausnahme.Wie läuft man lang laufenden Prozess mit Servlet

Aug 10, 2016 2:08:05 PM org.apache.catalina.core.StandardContext reload 
INFO: Reloading Context with name [/] has started 
Aug 10, 2016 2:08:05 PM org.apache.catalina.core.StandardWrapper unload 
INFO: Waiting for 1 instance(s) to be deallocated for Servlet [Servlet] 
Aug 10, 2016 2:08:06 PM org.apache.catalina.core.StandardWrapper unload 
INFO: Waiting for 1 instance(s) to be deallocated for Servlet [Servlet] 
Aug 10, 2016 2:08:07 PM org.apache.catalina.core.StandardWrapper unload 
INFO: Waiting for 1 instance(s) to be deallocated for Servlet [DayZeroServlet] 
Aug 10, 2016 2:08:07 PM org.apache.catalina.loader.WebappClassLoaderBase clearReferencesThreads 
WARNING: The web application [xxx#Day0MS] is still processing a request that has yet to finish. This is very likely to create a memory leak. You can control the time allowed for requests to finish by using the unloadDelay attribute of the standard Context implementation. Stack trace of request processing thread: 
java.net.SocketOutputStream.socketWrite0(Native Method) 
java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:109) 

Unten ist der Code, ich bin mit

protected void doGet(HttpServletRequest request, HttpServletResponse response) 
      throws ServletException, IOException { 
    PrintWriter out = response.getWriter(); 
    if (!GehDAO.getProcessFlag()) { 
     GehDAO.updateProcessFlag(true); 
     out.println("Transformation started ..."); 
     closeWriter(out); 
     execute(); // This step start the long running process 
    } 
    else { 
     out.println("Transformation Already Running ..."); 
     closeWriter(out); 
    } 
} 

Gibt es eine Möglichkeit ich die Methode execute() in separaten Prozess ausgeführt werden kann?

Ich wollte dieses Servlet einmal oder zweimal in einem Monat ausführen, um einen langwierigen Prozess zu starten.

+0

Beachten Sie, dass Ihr Code nicht Thread-sicher ist. – xehpuk

Antwort

1

Können Sie nicht einfach den execute() Anruf in einen Thread wickeln?

new Thread(() -> execute()).start(); 

Oder für ältere Pre-Java8:

new Thread(new Runnable() { 
    public void run() { execute(); } 
}).start(); 

One side note: Stellen Sie sicher, dass Sie das Herunterfahren verwalten. Sie können dies normalerweise mit einem ServletContextListener tun. Wenn der Kontext zerstört wird, legen Sie im Wesentlichen einen booleschen Flag für Ihren langen laufenden Thread fest, um ihn darüber zu informieren, dass er angehalten werden muss, da der App-Server darauf wartet, dass er beendet wird, um herunterzufahren.

+0

Grundsätzlich ist dies. Fork up einen neuen Thread und lassen Sie es drehen. Bonuspunkte von Ihren Endbenutzern, wenn Sie den Fortschritt ihrer Aufgabe überwachen, damit sie deren Fortschritt überwachen können; Ich habe herausgefunden, dass MongoDB gut ist, um solche Sachen zu speichern, aber jede andere Datenbank sollte funktionieren. Außerdem können Sie mithilfe einer Datenbank eine Aufgabenwarteschlange implementieren, sodass Ihre Benutzer nicht achtzehn Billiarden parallele Threads ausführen. – nasukkin

Verwandte Themen