質問

編集: 私は今、問題がに関連していると確信しています      while(true)ループは、コメントアウトした他のすべてのコマンドを保持し、アプリケーションは添付の例外なしでデプロイされます。それがどれほど重要かはわかりませんが、私の ServletContextListener の実装は次のようになります:

         パブリッククラスBidPushServiceはServletContextListener {

を実装します
public void contextInitialized(ServletContextEvent sce) {   
//Some init code not relevant, omitted for clarity
      BidPushThread t= new BidPushThread();
      t.setServletContext(sce.getServletContext());
      t.run();
}

したがって、アプリのデプロイ時にスレッドが実行されるようになりましたが、 while ループがコメント化されているため、実際の意味はありません。

アプリケーションの読み込み時にスレッドをバックグラウンドで実行し、常に(タイムアウトなしで)オブジェクトの特定のキューをチェックする必要があります。もちろん、オブジェクトがあると、「それらを処理します」。その後、キューのチェックを続けます。

現在、 ServletContextListener インターフェースを実装しており、アプリのロード時に呼び出されています。その中で、いくつかのメンテナンスを行い、 java.lang.Thread から継承したスレッドを開始します。

ここからが私の問題の始まりです(またはそう思います)。 run()メソッドには、

while (true) {
    //some code which doesn't put the thread to sleep ever
}

サーバーにアプリをデプロイしようとすると、 java.util.concurrent.TimeOutException が発生します。 私は何を間違えていますか?

常に実行されているスレッドはありませんか?アプリが削除されると、そのスレッドは ServletContextListener の対応するイベントによって停止されます。

本当にキューを遅滞なくチェックし続けるものが本当に必要です。

ご協力いただきありがとうございます!

編集:これはスタックトレースです

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)

マイコード:

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;
    }
}

フォーマットの混乱はごめんなさい。ただし、「4スペースずつコードをインデント」する限りは。私にはうまくいきません 編集:「BlockingQueue」について読んで実装しましたが、まったく同じ例外とスタックトレースを取得しています。 「BlockingQueue」の使用を反映するように上記のコードを変更しました

役に立ちましたか?

解決

コードは新しいスレッドを開始せず、同じスレッドでループを実行するため、デプロイ時にタイムアウトエラーが発生します。

スレッドを開始するには、runメソッドではなく、startメソッドを呼び出す必要があります。

public void contextInitialized(ServletContextEvent sce) {   
//Some init code not relevant, omitted for clarity
  BidPushThread t= new BidPushThread();
  t.setServletContext(sce.getServletContext());
  t.start();// run();
}

他のヒント

setDaemon

  

要約:

     
      
  • このスレッドをデーモンスレッドまたはユーザースレッドとしてマークします。の   Java仮想マシンは、   実行中のスレッドのみがすべてデーモンです   スレッド。
  •   
  • このメソッドは、スレッドを開始する前に呼び出す必要があります。
  •   
  • このメソッドは、まずこのスレッドのcheckAccessメソッドを呼び出します
      引数なし。これにより、   SecurityExceptionをスローします(
      現在のスレッド)。
  •   

スレッド

  

要約:多くの場合、私たちは本当に   バックグラウンドスレッドを作成したい   シンプルで定期的なタスクを   応用。 setDaemon()メソッド   としてスレッドをマークするために使用できます   殺すべきデーモンスレッド   他にない場合は破棄されます   アプリケーションスレッドは残ります。通常は、   Javaインタープリターは引き続き実行されます   すべてのスレッドが完了するまで。しかし   デーモンスレッドが唯一の場合   スレッドはまだ生きています、インタプリタ   終了します。

これは非常に悪い考えです。正当な理由なしに100%のCPU負荷が発生します。

正しい解決策は、おそらくキューが空のときにスレッドをブロックすることです。これは BlockingQueue で簡単に実装されます。

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.

&quot;そのスレッドは停止しています&quot ;?どうやって? while(true){...}ループには終了条件はありません。どうやって止めますか? Thread.stop()メソッドを使用していますか?これは安全ではなく、Java 1.1で非推奨になりました

setDaemon(true)を使用する場合、アプリサーバーの管理ツールを使用してWebアプリを停止した後、スレッドはアクティブのままになります。その後、Webアプリを再起動すると、別のスレッドが取得されます。 Webアプリケーションをアンデプロイしようとしても、スレッドは実行されたままになり、Webアプリケーション全体がガベージコレクションされるのを防ぎます。その後、次のバージョンを再デプロイすると、メモリ内のすべての追加コピーが提供されます。

ループに終了条件(たとえば、InterruptedExceptionまたはvolatile&quot; stopNow&quot;ブール値)を指定すると、この問題を回避できます。

java.langThread.setDaemon()メソッドを見てください。必要な場合があります

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top