2016-05-05 21 views
2

Tomcatを使用してRaspberry PIと通信するアプリケーションを開発しています。 GUIはhtmlで行われ、これら2つの間の通信はウェブソケットを使用して実現されます。ここまでは順調ですね。TomcatのExecutorServiceスレッドを停止

アプリが最初に実行されるときにスレッドを開始して、一連のタスクを開始したいとします。これは私が行ったテストです:

public class ContexService implements ServletContextListener { 

    Thread thread; 
    ExecutorService executorService; 

// ServiceManager serviceManager; 
    @Override 
    public void contextInitialized(ServletContextEvent sce) { 

     System.out.println("-------------> CONTEXT INITIALIZED <-------------"); 
     executorService = Executors.newSingleThreadExecutor(); 
     executorService.submit(new Runnable() { 
      @Override 
      public void run() { 
          Test p = new Test(); 
       int count = 0; 
       while (count < 20) { 
        p.imprimir(count); 
        count++; 
        try { 
         Thread.sleep(1000); 
        } catch (InterruptedException ex) { 
         System.out.println("error - > " + ex.getMessage()); 
        } 
      } 
     }}); 

} 

    @Override 
    public void contextDestroyed(ServletContextEvent sce) { 

     System.out.println("-------------> CONTEXT DESTROYED <-------------"); 
     if(executorService!=null) 
     { 
      if(!executorService.isShutdown()) 
      { 
       try { 
        executorService.shutdown(); 
        executorService.awaitTermination(3, TimeUnit.SECONDS); 
        if(!executorService.isTerminated()) 
        { 
         executorService.shutdownNow(); 
        } 
       } catch (InterruptedException ex) { 
        Logger.getLogger(ContexService.class.getName()).log(Level.SEVERE, null, ex); 
       } 
      } 
     } 

    } 
} 

私はこれを実行して動作します。私の問題は、Netbeansで "再生"を押すたびにすべてのものが再開される(これが私の望むものです)が、ExecutorService remaing activeを使ってスレッドが起動されるということです。 pool4スレッド1(私はそれを再起動し、スレッドが動作したまま、新しいスレッドが開始されたを使用してテストを印刷

-------------> CONTEXT DESTROYED <------------- 
05-May-2016 15:19:41.668 INFO [http-apr-8080-exec-66] org.apache.catalina.startup.HostConfig.undeploy Repliegue (undeploy) de la aplicación web que tiene como trayectoria de contexto /safemo 
05-May-2016 15:19:41.694 INFO [http-apr-8080-exec-65] org.apache.catalina.startup.HostConfig.deployDescriptor Desplieque del descriptor de configuración C:\apache-tomcat-8.0.33\conf\Catalina\localhost\safemo.xml 
05-May-2016 15:19:42.268 INFO [http-apr-8080-exec-65] org.apache.catalina.startup.HostConfig.deployDescriptor Deployment of configuration descriptor C:\apache-tomcat-8.0.33\conf\Catalina\localhost\safemo.xml has finished in 574 ms 
05-May-2016 15:19:42.273 INFO [http-apr-8080-exec-69] org.apache.catalina.util.LifecycleBase.start The start() method was called on component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/safemo]] after start() had already been called. The second call will be ignored. 
-------------> CONTEXT INITIALIZED <------------- 
15:19:42.446 [pool-4-thread-1] DEBUG sal.Test - 0 --> TEST <--Thu May 05 15:19:42 CEST 2016 
15:19:43.455 [pool-4-thread-1] DEBUG sal.Test - 1 --> TEST <--Thu May 05 15:19:42 CEST 2016 
15:19:44.456 [pool-4-thread-1] DEBUG sal.Test - 2 --> TEST <--Thu May 05 15:19:42 CEST 2016 
15:19:45.456 [pool-4-thread-1] DEBUG sal.Test - 3 --> TEST <--Thu May 05 15:19:42 CEST 2016 
15:19:46.456 [pool-4-thread-1] DEBUG sal.Test - 4 --> TEST <--Thu May 05 15:19:42 CEST 2016 
-------------> CONTEXT DESTROYED <------------- 
15:19:47.456 [pool-4-thread-1] DEBUG sal.Test - 5 --> TEST <--Thu May 05 15:19:42 CEST 2016 
15:19:48.456 [pool-4-thread-1] DEBUG sal.Test - 6 --> TEST <--Thu May 05 15:19:42 CEST 2016 
15:19:49.457 [pool-4-thread-1] DEBUG sal.Test - 7 --> TEST <--Thu May 05 15:19:42 CEST 2016 
error - > sleep interrupted 
15:19:49.484 [pool-4-thread-1] DEBUG sal.Test - 8 --> TEST <--Thu May 05 15:19:42 CEST 2016 
05-May-2016 15:19:49.487 WARNING [http-apr-8080-exec-77] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [safemo] appears to have started a thread named [pool-4-thread-1] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread: 
java.lang.Thread.sleep(Native Method) 
sal.ContexService$1.run(ContexService.java:42) 
java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) 
java.util.concurrent.FutureTask.run(FutureTask.java:266) 
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) 
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) 
java.lang.Thread.run(Thread.java:745) 
05-May-2016 15:19:49.991 INFO [http-apr-8080-exec-77] org.apache.catalina.startup.HostConfig.undeploy Repliegue (undeploy) de la aplicación web que tiene como trayectoria de contexto /safemo 
05-May-2016 15:19:50.034 INFO [http-apr-8080-exec-63] org.apache.catalina.startup.HostConfig.deployDescriptor Desplieque del descriptor de configuración C:\apache-tomcat-8.0.33\conf\Catalina\localhost\safemo.xml 
15:19:50.484 [pool-4-thread-1] DEBUG sal.Test - 9 --> TEST <--Thu May 05 15:19:42 CEST 2016 
05-May-2016 15:19:50.682 INFO [http-apr-8080-exec-63] org.apache.catalina.startup.HostConfig.deployDescriptor Deployment of configuration descriptor C:\apache-tomcat-8.0.33\conf\Catalina\localhost\safemo.xml has finished in 648 ms 
05-May-2016 15:19:50.686 INFO [http-apr-8080-exec-70] org.apache.catalina.util.LifecycleBase.start The start() method was called on component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/safemo]] after start() had already been called. The second call will be ignored. 
-------------> CONTEXT INITIALIZED <------------- 
15:19:50.818 [pool-5-thread-1] DEBUG sal.Test - 0 --> TEST <--Thu May 05 15:19:50 CEST 2016 
15:19:51.484 [pool-4-thread-1] DEBUG sal.Test - 10 --> TEST <--Thu May 05 15:19:42 CEST 2016 
15:19:51.824 [pool-5-thread-1] DEBUG sal.Test - 1 --> TEST <--Thu May 05 15:19:50 CEST 2016 
15:19:52.485 [pool-4-thread-1] DEBUG sal.Test - 11 --> TEST <--Thu May 05 15:19:42 CEST 2016 
15:19:52.825 [pool-5-thread-1] DEBUG sal.Test - 2 --> TEST <--Thu May 05 15:19:50 CEST 2016 
15:19:53.485 [pool-4-thread-1] DEBUG sal.Test - 12 --> TEST <--Thu May 05 15:19:42 CEST 2016 
15:19:53.825 [pool-5-thread-1] DEBUG sal.Test - 3 --> TEST <--Thu May 05 15:19:50 CEST 2016 
15:19:54.485 [pool-4-thread-1] DEBUG sal.Test - 13 --> TEST <--Thu May 05 15:19:42 CEST 2016 
15:19:54.825 [pool-5-thread-1] DEBUG sal.Test - 4 --> TEST <--Thu May 05 15:19:50 CEST 2016 
15:19:55.486 [pool-4-thread-1] DEBUG sal.Test - 14 --> TEST <--Thu May 05 15:19:42 CEST 2016 
15:19:55.826 [pool-5-thread-1] DEBUG sal.Test - 5 --> TEST <--Thu May 05 15:19:50 CEST 2016 
15:19:56.486 [pool-4-thread-1] DEBUG sal.Test - 15 --> TEST <--Thu May 05 15:19:42 CEST 2016 
15:19:56.826 [pool-5-thread-1] DEBUG sal.Test - 6 --> TEST <--Thu May 05 15:19:50 CEST 2016 
15:19:57.486 [pool-4-thread-1] DEBUG sal.Test - 16 --> TEST <--Thu May 05 15:19:42 CEST 2016 
15:19:57.826 [pool-5-thread-1] DEBUG sal.Test - 7 --> TEST <--Thu May 05 15:19:50 CEST 2016 
15:19:58.486 [pool-4-thread-1] DEBUG sal.Test - 17 --> TEST <--Thu May 05 15:19:42 CEST 2016 
15:19:58.826 [pool-5-thread-1] DEBUG sal.Test - 8 --> TEST <--Thu May 05 15:19:50 CEST 2016 
15:19:59.486 [pool-4-thread-1] DEBUG sal.Test - 18 --> TEST <--Thu May 05 15:19:42 CEST 2016 
15:19:59.826 [pool-5-thread-1] DEBUG sal.Test - 9 --> TEST <--Thu May 05 15:19:50 CEST 2016 
15:20:00.486 [pool-4-thread-1] DEBUG sal.Test - 19 --> TEST <--Thu May 05 15:19:42 CEST 2016 
15:20:00.827 [pool-5-thread-1] DEBUG sal.Test - 10 --> TEST <--Thu May 05 15:19:50 CEST 2016 
15:20:01.827 [pool-5-thread-1] DEBUG sal.Test - 11 --> TEST <--Thu May 05 15:19:50 CEST 2016 
15:20:02.827 [pool-5-thread-1] DEBUG sal.Test - 12 --> TEST <--Thu May 05 15:19:50 CEST 2016 
15:20:03.827 [pool-5-thread-1] DEBUG sal.Test - 13 --> TEST <--Thu May 05 15:19:50 CEST 2016 
15:20:04.827 [pool-5-thread-1] DEBUG sal.Test - 14 --> TEST <--Thu May 05 15:19:50 CEST 2016 
15:20:05.827 [pool-5-thread-1] DEBUG sal.Test - 15 --> TEST <--Thu May 05 15:19:50 CEST 2016 
15:20:06.827 [pool-5-thread-1] DEBUG sal.Test - 16 --> TEST <--Thu May 05 15:19:50 CEST 2016 
15:20:07.828 [pool-5-thread-1] DEBUG sal.Test - 17 --> TEST <--Thu May 05 15:19:50 CEST 2016 
15:20:08.828 [pool-5-thread-1] DEBUG sal.Test - 18 --> TEST <--Thu May 05 15:19:50 CEST 2016 
15:20:09.828 [pool-5-thread-1] DEBUG sal.Test - 19 --> TEST <--Thu May 05 15:19:50 CEST 2016 

は私がアプリを起動し、起動します:あなたは私が何を意味するか見て私は、Tomcatのコンソール出力を添付しますプール5スレッド1)。

contextDestroyedで「executorService.shutDown」を実行すると、スレッドが停止しないのはなぜですか?

ありがとうございました!

+0

スレッドはまだ後で実行されていますか?すべてが止まるまでに時間がかかることがあります。あなたの 'Runnable'がまだ動いているかどうかのようないくつかのステータス情報を出力してみませんか?あなたのスレッドは仕事をするのに10秒を要し、アプリケーションをかなり早くシャットダウンしています。 Javaはスレッドを実際にはほとんど終了しません。そのため、executorは「シャットダウン」しているかもしれませんが、そのスレッドはおそらくまだ実行中です。 –

答えて

1

あなたの質問に解決するには、2つの謎があるように思え:

MYSTERY1:なぜそれは停止しないのだろうか? 実行方法を確認します:ループは20回(0から19まで)ループし、ループするたびに1秒間待機します。したがって、少なくとも20秒間は実行されません。

シャットダウンが3秒間だけ待ちます。その時までに、あなたの仕事は終わらない。あなたは、この行を置き換えるために試みることができる:これで

executorService.awaitTermination(3, TimeUnit.SECONDS); 

:あなたのタスクは、本当に終わるまで

executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS); 

その方法、それは待機します。注:あなたが待っていなくても、すぐにshutdownNowを呼び出しても、それはうまくいかないでしょう。コードのその部分をリファクタリングして、単に20回ループするのではなく、ループ処理中にスレッドが中断しているかどうかをチェックして、処理を完全に完了(短絡)できるようにする必要があります。この1と

while (count<20) { 

:この行を変更してみ

このソリューションは、私が言ったことを説明するのに役立つはずです
while (count<20 && !Thread.currentThread().isInterrupted()) { 

以上:また Why ExecutorService.shutdownNow method can't stop the thread shutdownNowのためにドキュメントを読む価値:http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ExecutorService.html

実行中のタスクの処理を停止しようとするベストエフォート型の試み以外の保証はありません。例えば、典型的な実装はThread.interrupt()を介して取り消されるので、割り込みに応答しないタスクは決して終了しないかもしれません。

MYSTERY2:なぜNetbeansは2つのスレッドを同時に実行していますか? これは、実行中のスレッドが処理を停止しておらず、その途中で中断要求を処理していないためです。したがって、これはすべて予想されます。プログラムは完了するまで実行され続けます(javaはコードを停止するように指示していますが、コードは現在そのメッセージをリッスンしていません)。つまり、プログラムを再起動すると同時に両方のスレッドが同時に実行されています(以前の実行はまだ実行されており、別のスレッドを開始しています)。スレッドが20番目のループ(index = 19)に達すると、スレッドがクリーンアップされ、JVMが最終的にシャットダウンするようになります。私はcontextDestroyedの「executorService.shutDown」を実行した場合、スレッドが停止されていないのはなぜ https://netbeans.org/bugzilla/show_bug.cgi?id=232322

0

:あなたはそれを実行しているJVMを残しNetBeansのバグに遭遇しない限り、それは、ありますか?

シャットダウンExecutorServiceは、Oracleのマニュアルページで推奨されています。

あなたの方法は

public void contextDestroyed(ServletContextEvent sce) { 

    executorService.shutdown(); // Disable new tasks from being submitted 
     try { 
     // Wait a while for existing tasks to terminate 
     if (!executorService.awaitTermination(60, TimeUnit.SECONDS)) { 
      executorService.shutdownNow(); // Cancel currently executing tasks 
      // Wait a while for tasks to respond to being cancelled 
      if (!executorService.awaitTermination(60, TimeUnit.SECONDS)) 
       System.err.println("executorService did not terminate"); 
     } 
     } catch (InterruptedException ie) { 
     // (Re-)Cancel if current thread also interrupted 
     executorService.shutdownNow(); 
     // Preserve interrupt status 
     Thread.currentThread().interrupt(); 
     } 
} 

shutdown():を変更する必要がありますが、以前に提出されたタスクが実行される通常のシャットダウンを開始しますが、新しいタスクは受け入れられません。

shutdownNow():アクティブに実行中のタスクをすべて停止しようとし、待機中のタスクの処理を停止し、実行を待っていたタスクのリストを返します。

あなたは上記のコードに従って適切にシャットダウンを扱う場合

while (!executorService.awaitTermination(60, TimeUnit.SECONDS)) 
Thread.sleep(60000); 

if (!executorService.awaitTermination(60, TimeUnit.SECONDS)) 

からExecutorService

をシャットダウンするための長い期間の場合で以下のように、この条件を変更することができ、複数のExecutorServiceプールで2番目の問題が発生することはありません。

関連する問題