如何创建一个在我的应用程序运行时一直运行的线程

时间:2009-09-10 07:03:05

标签: java multithreading deployment servlets timeout

编辑: 我现在确定问题与此有关     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();
}

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)

很抱歉格式化混乱,但对于我的“缩进代码4个空格”的生命,对我来说不起作用 编辑:阅读'BlockingQueue'并实现它,但我仍然得到完全相同的异常和堆栈跟踪。更改了上面的代码以反映'BlockingQueue'的使用

5 个答案:

答案 0 :(得分:5)

setDaemon

  

内容:

     
      
  • 将此线程标记为守护程序线程或用户线程。该   Java虚拟机退出时   只有运行的线程都是守护进程   线程。
  •   
  • 必须在线程启动之前调用此方法。
  •   
  • 此方法首先调用此线程的checkAccess方法   没有参数。这可能导致   抛出一个SecurityException(在   当前线程)。
  •   

Threads

  

总结:在很多情况下,我们真正的   想要创建后台线程   做一个简单的周期性任务   应用。 setDaemon()方法   可以用来将Thread标记为   应该被杀死的守护程序线程   没有别的时候丢弃   应用程序线程仍然一般,   Java解释器继续运行   直到所有线程都完成。但   当守护程序线程是唯一的   线程还活着,解释器   将退出。

答案 1 :(得分:3)

这将是一个非常糟糕的主意。没有充分理由,你会导致100%的CPU负载。

正确的解决方案可能是在队列为空时阻塞线程。这可以通过BlockingQueue轻松实现。

答案 2 :(得分:3)

您的代码没有启动新线程,它在同一个线程中运行循环,这就是您在部署时遇到超时错误的原因。

要启动一个线程,你必须调用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 :(得分:1)

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),则在使用app-server的管理工具停止Web应用程序后,该线程将保持活动状态。然后,如果您重新启动Web应用程序,您将获得另一个线程。即使您尝试取消部署Web应用程序,该线程仍将继续运行,并将阻止整个Web应用程序被垃圾收集。然后重新部署下一个版本将为您提供内存中所有内容的附加副本。

如果为循环提供退出条件(例如InterruptedException或volatile“stopNow”boolean),则可以避免此问题。

答案 4 :(得分:0)

看一下java.langThread.setDaemon()方法,可能就是你需要的东西