每n分钟新线程(java.lang.Thread.State:在sun.misc.Unsafe.park(原生方法)等待)

时间:2015-05-04 12:31:56

标签: java glassfish

我阅读了所有现有主题,但我没有找到解决问题的方法。我用VisualVM监视我的glassfish服务器,我发现了一些奇怪的行为。这是截图:

enter image description here

java.lang.Thread.State: WAITING
    at sun.misc.Unsafe.park(Native Method)
    - parking to wait for <3cb9965d> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
    at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
    at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1088)
    at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
    at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)

正如您所见,每20分钟创建一个新线程(下一个,将创建Thread-38,然后创建Thread-39,依此类推)。这些线程永远不会完成。我正在使用来自类Executors的newSingleThreadExecutor(),它使用scheduleWithFixedDelay()进行调度,延迟时间为100毫秒,其他代码只是数据库读/写(所以没有什么特别的东西可以创建新的等待线程)...有人知道什么可能造成这个问题?

ScheduledExecutorService service = service = Executors.newSingleThreadScheduledExecutor();
service.scheduleWithFixedDelay(new Runnable() {
            @Override
            public void run() {
                //do something...
            }
        }, 1, readInterval, TimeUnit.MILLISECONDS);

编辑:即使没有应用程序部署到服务器,每20分钟创建一个新线程。有没有人注意到类似的问题?我还注意到所有新线程都在等待相同的ID(在此示例中&lt; 3cb9965d&gt;)...

1 个答案:

答案 0 :(得分:1)

也许你的观察反映了线程池的行为......

如果某个线程在线程池中空闲了一段时间,它将从线程池中删除

根据您在glassfish的domain.xml 中的设置,将创建一个新线程以满足池中的最小线程数。 请注意,如果您没有在domain.xml文件中指定它们,则glassfish会使用自己的默认值。

线程具有相同的ID,因为它们属于同一个线程池

验证您是否可以将属性 idle-thread-timeout-seconds =&#34; 300&#34; 添加到 http-thread-pool 中domain.xml并使用VisualVM再次检查它。

&#13;
&#13;
 <thread-pool idle-thread-timeout-seconds="300" name="http-thread-pool"></thread-pool>
&#13;
&#13;
&#13;

以上将空闲线程的超时设置为5分钟。也许你找到&#34; idle-thread-timeout-seconds =&#34; 1200&#34;你的domain.xml中的某个地方,这可以解释你观察到的20分钟的间隔......

进一步说明:
如果您查看domain.xml,您可能会发现以下条目(您的可能不同......):

&#13;
&#13;
   [...]

<!-- HTTP -->
<network-listener protocol="http-listener-1" port="8080" 
    name="http-listener-1" thread-pool="http-thread-pool" 
    transport="tcp"></network-listener>
<!--HTTPS -->
<network-listener protocol="http-listener-2" port="8181" 
   name="http-listener-2" thread-pool="http-thread-pool"
   transport="tcp"></network-listener>
   [...]

<!--Threadpools wich can be used by network-listeners-->
<thread-pools>
    <thread-pool name="admin-thread-pool" max-queue-size="256" max-thread-pool-size="50"></thread-pool>
    <thread-pool name="http-thread-pool"></thread-pool>
    <thread-pool name="thread-pool-1" max-thread-pool-size="200"></thread-pool>
  </thread-pools>

[...]
&#13;
&#13;
&#13;

如您所见,没有为线程池&#34; http-thread-pool&#34; 指定属性。这意味着galssfish将使用自己的默认值。

&#34; http-thread-pool&#34;的默认值在我的glassfish安装(4.1)中有以下值*:

  • 最大队列大小:4096
  • 最大线程池大小:5
  • 最小线程池大小:5
  • 空闲线程超时:900(秒)

在这种情况下,如果一个线程已空闲15分钟,它将从线程池中删除。由于&#34;最小线程池大小= 5&#34;如果线程数低于5,将创建一个新线程。

*您可以进入glassfish的管理控制台并打开  &#34;配置 - &gt; server-config - &gt;线程池&#34;找出你的默认值。