Java newScheduledThreadPool(1)和newSingleThreadScheduledExecutor()之间的差异
我想知道Executors类的这两种方法之间的区别是什么?我有一个web应用程序,每100毫秒检查一次数据,所以我使用scheduleWithFixedDelay方法的调度程序。我想知道在这种情况下应该使用哪种方法(newScheduledThreadPool或newSingleThreadScheduledExecutor)? 我还有一个问题-在我监视Glassfish服务器的VisualVM中,我注意到我在PARK state中有一些线程-例如:Java newScheduledThreadPool(1)和newSingleThreadScheduledExecutor()之间的差异,java,Java,我想知道Executors类的这两种方法之间的区别是什么?我有一个web应用程序,每100毫秒检查一次数据,所以我使用scheduleWithFixedDelay方法的调度程序。我想知道在这种情况下应该使用哪种方法(newScheduledThreadPool或newSingleThreadScheduledExecutor)? 我还有一个问题-在我监视Glassfish服务器的VisualVM中,我注意到我在PARK state中有一些线程-例如: java.lang.Thread.State
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)
java.lang.Thread.State:正在等待
在sun.misc.Unsafe.park(本机方法)
-停车等待(java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
位于java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
位于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.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
位于java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
位于java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
运行(Thread.java:745)
有没有可能因为我不知道还有什么会创建这些线程而将它们与调度程序连接?这些线从来没有被破坏过,所以我担心这会引起一些麻烦。这是一个屏幕截图(新线程35将在15分钟内创建,以此类推……):
如前所述:
与其他等效的newScheduledThreadPool(1)不同,返回的执行器保证不可重新配置以使用其他线程
因此,当使用newScheduledThreadPool(1)
时,您以后可以添加更多线程。newSingleThreadScheduledExecuto()由委托包装,如您在Executors.java中所见:
差异(来自javadoc):
如果此单线程在关机前的执行过程中由于故障而终止,则在需要执行后续任务时,将替换一个新线程
与其他等价的{@code newScheduledThreadPool(1)}不同,返回的执行器保证不可重新配置以使用其他线程
答复你的评论:
这是否也适用于newScheduledThreadPool(1)
不,您需要自己处理线程故障
至于不安全的.park(),请参见。正如wings和tagir所指出的,区别在于“如何管理故障” 关于线程您的线程处于等待状态
park
不是状态,而是将线程置于等待状态的方法;另见
然而,让我建议一种在JavaEE上实现调度线程的不同方法;您应该看看EJB的
线程池是具有预先配置的线程数的线程池/线程组(首先)。如果您有一个工作密集型场景,其中池中的每个线程可能工作更长的时间,并且您希望更快地完成工作,那么这非常有用,因此您可以创建一个线程池。单线程——顾名思义,就是一个线程反复执行。根据工作的性质和任务的复杂性,您可以在单个线程或线程池之间进行选择。所以在以后添加更多线程有什么区别?关于此语句(来自NewsingleThreadExecutor的文档):“(但是,请注意,如果此单线程在关机之前的执行过程中由于故障而终止,则在需要执行后续任务时,将替换一个新线程。)”-这是否也适用于newScheduledThreadPool(1)?是,它也适用。实际的区别是
newScheduledThreadPool(N)
与N
>1将使许多线程保持空闲状态。计划的任务可以在不同的线程中运行,但它们遵循before
模型,在本例中,这基本上意味着不会有两个计划的任务并行运行(为完全相同的执行时间计划的任务以先进先出(FIFO)提交顺序启用)。如果当前线程死亡,可以从池中简单地获取一个新线程,这可能会更快。Executor将保持线程数为N
。好的,谢谢。因此,对于我的情况,我认为可以使用newSingleThreadScheduledExecutor()。是否可能是因为使用了newSingleThreadScheduledExecutor(),所以我有了这些驻车状态线程(请参见上面的屏幕截图)?编辑:我已经看到了关于Unsafe.park()的主题,但我不知道是什么原因造成的,所以我想知道是否有人知道调度程序是否存在任何问题…@user4341206抱歉,我不确定。但这似乎是可能的。因为即使在空闲时,单个线程仍将保留在线程池中。当旧线程未及时完成时,新任务仍将添加到线程池中。以上问题“这是否也适用于newScheduledThreadPool(1)”的答案为“是”。传递给ScheduledThreadPoolExecutor的构造函数的1
是corePoolSize
。除非您将其设置为0
(不推荐),否则如果先前执行的线程因异常而死亡并且需要一个异常,则ScheduledThreadPoolExecutor
将重新创建线程。newSingleThreadScheduledExecutor()
和newScheduledThreadPool(1)
之间的唯一区别在于,在第一种情况下,执行器保证不可重新配置以使用其他线程。区别在于delegatedScheduledexecutor服务仅公开schedule
和invoke
public static ScheduledExecutorService newSingleThreadScheduledExecutor() {
return new DelegatedScheduledExecutorService(new ScheduledThreadPoolExecutor(1));
}
@Singleton
public class TimerSessionBean {
@Resource
TimerService timerService;
public void setTimer(long intervalDuration) {
Timer timer = timerService.createTimer(intervalDuration,
"Created new programmatic timer");
}
@Timeout
public void lookForData(Timer timer) {
//this.setLastProgrammaticTimeout(new Date());
....
}
//OR
@Schedule(minute = "*/1", hour = "*")
public void runEveryMinute() {
...
}
}