2015-11-02 140 views
0

我一直在使用弹簧引导与@Scheduled一段时间,但最近我发现有一个危险的潜在威胁,如下所述: 我发现应用程序运行和计划任务运行几次,有很多线程仍然在等待,但没有完成,这在线程堆栈跟踪中显示为'kill -3'。要清除任何可能导致这个问题,我做一个完全虚拟的任务:弹簧启动计划任务挂起

@Component 
public class TestJob 
{ 
    /** 
    * LOGGER 
    */ 
    private static Logger log = LogManager.getLogger(TestJob.class); 

    @Scheduled(fixedDelay = 60000, initialDelay = 1000) 
    public void test() 
    { 
     log.info("---------------[{}]", Thread.currentThread().getId()); 
    } 
} 

,这是我的日志:

20151102 11:54:50.660 | INFO | pool-3-thread-2 | --------------- [26] | TestJob.test(TestJob.java:19) 20151102 11:55:50.662 | INFO | pool-3-thread-4 | --------------- [28] | TestJob.test(TestJob.java:19) 20151102 11:56:50.664 | INFO | pool-3-thread-5 | --------------- [33] | TestJob.test(TestJob.java:19) 20151102 11:57:50.666 | INFO | pool-3-thread-6 | --------------- [37] | TestJob.test(TestJob.java:19)

线程堆栈跟踪:

“池-3-线程2” #26 PRIO = 5 os_prio = 0 TID = 0x00007fbea0cd9800 NID = 0x74f2等待条件[0x00007fbf0d3d2000] java.lang.Thread.State:WAITING(停车) at sun.misc.Unsafe.park(本地方法) - 停车等待< 0x0000000763ed3710>(一个java.util.concurrent.locks.AbstractQueuedSynchronizer $ ConditionObject) at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175) at java.util.c oncurrent.locks.AbstractQueuedSynchronizer $ ConditionObject.await(AbstractQueuedSynchronizer.java:2039) 在java.util.concurrent.ScheduledThreadPoolExecutor中的$ DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1088) 在java.util.concurrent.ScheduledThreadPoolExecutor中的$ DelayedWorkQueue.take( ScheduledThreadPoolExecutor.java:809) 在java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067) 在java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127) 在java.util.concurrent中。的ThreadPoolExecutor $ Worker.run(ThreadPoolExecutor.java:617) 在java.lang.Thread.run(Thread.java:745)

“池-3-螺纹-4” #28 PRIO = 5 os_prio = 0 TID = 0x00007fbea0783 800 NID = 0x74f4等待条件[0x00007fbf0d1d0000] java.lang.Thread.State中:WAITING(停车场) 在sun.misc.Unsafe.park(本机方法) - 停车等待< 0x0000000763ed3710>(个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 ) 在java.util.concurrent.ScheduledThreadPoolExecutor中的$ DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1088) 在java.util.concurrent.ScheduledThreadPoolExecutor中的$ DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809) 在java.util.concurrent.ThreadPoolExec utor.getTask(ThreadPoolExecutor.java:1067) 在java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127) 在java.util.concurrent.ThreadPoolExecutor中的$ Worker.run(ThreadPoolExecutor.java:617) 在java.lang.Thread.run(线程。的java:745)

已调度的Javadoc说是通过注册ScheduledAnnotationBeanPostProcessor执行@Scheduled注释

处理。

我没有自己命名这个类,只有@EnableScheduling带注释的主类。

有谁知道如何解决这个问题?

UPDATE: I attached a picture of Eclipse debugging screen capture, the pool is increasing and all old threads are running... hope it can clarify my question.

我重视的Eclipse调试屏幕捕捉的图片,池正在增加,所有旧线程正在运行...希望能澄清我的问题。

更新: 我觉得我这次是对的。弹簧引导调度器的默认池大小为100,并且所有线程都处于运行状态。我真的不明白,跑什么?我认为它应该等待什么,为什么不呢? 有谁知道如何配置带注释的弹簧引导计划池大小?我没有在我的应用程序中使用xml,也不愿意仅为调度程序引入它。

+0

增加池大小会有帮助吗? – Sanjay

回答

1

我看你的例子中绝对正常的行为。 您有计划任务,它由线程池中的不同线程每分钟执行一次。线程池中的线程处于线程池期望的WAITING(驻留)状态。 如果你想减少线程的数目则可以配置: http://docs.spring.io/spring/docs/4.0.x/spring-framework-reference/htmlsingle/#scheduling

<task:scheduler id="scheduler" pool-size="2"/> 
+0

谢谢阿纳托利,其实我不会增加或减少游泳池的大小,但想要终止线程。如上所示,确切的线程处于等待状态,没有终止。每次作业运行时,它都会创建一个具有已停用线程ID的新线程,但线程永远不会终止。你遇到过这种情况吗? – Simon

+0

对不起,我犯了一个错误,每次都不一定很明显。但确实原始线程似乎没有终止。 – Simon

+0

未终止的线程数取决于您的池配置。线程不会因性能原因而终止 - 这是线程池如何工作的方式。只需对执行次数进行测试,然后再对池大小进行测试,您将看到线程被重用。我之前想到的是 –

0

检查这个link,这其中有对如何使用注释来实现更多的解释。