문제

편집 : 이제 문제가 while (true) 내가 언급 한대로 다른 모든 명령을 보유하고 있으며 첨부 된 예외없이 응용 프로그램이 배포됩니다. 얼마나 중요한지 잘 모르겠지만 내 ServletContextListener 구현은 다음과 같습니다.

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

이제 앱이 배포 될 때 스레드가 실행되지만 while 루프는 실제 의미가 없다고 언급됩니다.

애플리케이션이로드 될 때는 배경에서 스레드를 실행해야하며 (시간 초과없이) 객체에 대한 특정 대기열을 확인합니다. 물론 일단 물체가 있으면 "그들을 돌보고"대기열을 계속 확인합니다.

현재, 나는 그것을 구현하고 있습니다 ServletContextListener 인터페이스와 앱이로드 될 때 호출되고 있습니다. 그것에서 나는 몇 가지 유지 보수를하고 내가 상속받은 스레드를 시작합니다. java.lang.Thread.

여기 내 문제가 시작되는 곳이 있습니다 (또는 내 생각). 내 run() 방법, 나는 a

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'의 사용을 반영하도록 위의 코드를 변경했습니다.

도움이 되었습니까?

해결책

코드는 새 스레드를 시작하지 않고 동일한 스레드에서 루프를 실행하므로 배포 될 때 타임 아웃 오류가 발생하는 이유입니다.

스레드를 시작하려면 실행 메소드가 아닌 시작 메소드를 호출해야합니다.

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

다른 팁

세트 데몬

요약:

  • 이 스레드를 데몬 스레드 또는 사용자 스레드로 표시합니다. 실행중인 유일한 스레드가 모두 데몬 스레드 일 때 Java 가상 머신이 종료됩니다.
  • 스레드가 시작되기 전에이 방법을 호출해야합니다.
  • 이 방법은 먼저이 스레드의 CheckAccess 메소드를 호출합니다.
    논쟁이 없습니다. 이로 인해 SecurityException이 발생할 수 있습니다 (
    현재 스레드).

스레드

요약 : 많은 경우, 우리가 실제로 원하는 것은 응용 프로그램에서 간단하고 정기적 인 작업을 수행하는 배경 스레드를 만드는 것입니다. SetDaemon () 메소드는 스레드를 데몬 스레드로 표시하는 데 사용될 수 있으며 다른 응용 프로그램 스레드가 남아 있지 않을 때 제거하고 폐기해야합니다. 일반적으로 Java 통역사는 모든 스레드가 완료 될 때까지 계속 실행됩니다. 그러나 데몬 스레드가 여전히 살아있는 유일한 스레드 인 경우 통역사가 종료됩니다.

이것은 매우 나쁜 생각 일 것입니다. 당신은 정당한 이유없이 100% CPU로드를 일으킬 것입니다.

올바른 솔루션은 큐가 비어있을 때 스레드를 차단하는 것일 수 있습니다. 이것은 사소하게 구현되어 a 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.

"그 실이 멈췄다"? 어떻게? 당신의 기간에는 종료 조건이 없습니다 (true) {...} loop. 어떻게 멈추고 있습니까? Thread.stop () 메소드를 사용하고 있습니까? 안전하지 않고 Java 1.1에서 더 이상 사용되지 않았습니다.

SetDaemon (True)을 사용하는 경우 앱 서버의 관리 도구를 사용하여 웹 애플을 중지 한 후 스레드가 활성화됩니다. 그런 다음 웹 앱을 다시 시작하면 다른 스레드가 나타납니다. 웹 앱을 배포하려고하더라도 스레드는 계속 실행되며 전체 웹 애플이 쓰레기 수집을 방지하지 못하게됩니다. 그런 다음 다음 버전을 재배치하면 메모리에있는 모든 것의 추가 사본이 제공됩니다.

루프에 대한 종료 조건 (예 : InterruptedException 또는 휘발성 "StopNow"부울)을 제공하는 경우이 문제를 피할 수 있습니다.

java.langthread.setdaemon () 메소드를 살펴보십시오.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top