Как создать поток, который запускается все время, пока работает мое приложение - PullRequest
5 голосов
/ 10 сентября 2009

EDIT: Теперь я уверен, что проблема связана с while (true) цикл, содержащий все остальные команды, как я их закомментировал, и приложение развертывается без присоединенного исключения. Я не уверен, насколько это важно, но моя реализация ServletContextListener выглядит так:

public class BidPushService implements ServletContextListener{</p> <pre><code>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'

Ответы [ 5 ]

5 голосов
/ 10 сентября 2009

setDaemon

РЕЗЮМЕ:

  • Помечает этот поток как поток демона или как поток пользователя. Виртуальная машина Java завершается, когда только работающие потоки - все это демон потоки.
  • Этот метод должен быть вызван до запуска потока.
  • Этот метод сначала вызывает метод checkAccess этого потока
    без аргументов. Это может привести к выбрасывая SecurityException (в
    текущая тема).

Тема

РЕЗЮМЕ: Во многих случаях то, что мы на самом деле хочу создать фоновые темы которые делают простые периодические задачи в приложение. Метод setDaemon () может использоваться, чтобы пометить тему как поток демона, который должен быть убит и выбрасывается, когда никто другой Потоки приложений остаются. Обычно, интерпретатор Java продолжает работать пока все темы не завершены. Но когда потоки демона являются единственными темы еще живы, переводчик выйдет.

3 голосов
/ 10 сентября 2009

Ваш код не запускает новый поток, он запускает цикл в том же потоке, и поэтому при развертывании вы получаете ошибку тайм-аута.

Чтобы запустить поток, вы должны вызвать метод start, а не метод run.

public void contextInitialized(ServletContextEvent sce) {   
//Some init code not relevant, omitted for clarity
  BidPushThread t= new BidPushThread();
  t.setServletContext(sce.getServletContext());
  t.start();// run();
}
3 голосов
/ 10 сентября 2009

Это была бы очень плохая идея. Вы бы вызвали 100% загрузку процессора без веской причины.

Правильное решение - блокировать поток, когда очередь пуста. Это тривиально реализуется с помощью BlockingQueue.

1 голос
/ 10 сентября 2009
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.

"Этот поток остановлен"? Как? В вашем цикле while (true) {...} нет условия завершения. Как ты это прекратил? Вы используете метод Thread.stop ()? Это небезопасно и устарело в Java 1.1

Если вы используете setDaemon (true), поток останется активным после того, как вы остановили веб-приложение с помощью инструментов управления вашего сервера приложений. Затем, если вы перезапустите веб-приложение, вы получите другую ветку. Даже если вы попытаетесь отменить развертывание веб-приложения, поток останется запущенным и предотвратит сборку мусора всего веб-приложения. Затем повторное развертывание следующей версии даст вам дополнительную копию всего в памяти.

Если вы предоставите условие выхода для цикла (например, InterruptedException или переменное логическое значение stopNow), вы можете избежать этой проблемы.

0 голосов
/ 10 сентября 2009

Взгляните на метод java.langThread.setDaemon (), может это то, что вам нужно

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...