今天,我发现我的Java 8应用程序有很多线程处于等待状态:
[arthas@1]$ thread --state RUNNABLE
Threads Total: 3427, NEW: 0, RUNNABLE: 17, BLOCKED: 0, WAITING: 3114, TIMED_WAITING: 296, TERMINATED: 0
ID NAME GROUP PRIORITY STATE %CPU TIME INTERRUPTED DAEMON
124 pool-11-thread-25 main 5 RUNNABLE 75 0:0 false false
53 as-command-execute-daemon system 10 RUNNABLE 23 0:0 false true
133 Thread-20 main 5 RUNNABLE 1 0:2 false true
28 Apollo-RemoteConfigLongPollService-1 Apollo 5 RUNNABLE 0 0:0 false true
32 Attach Listener system 9 RUNNABLE 0 0:0 false true
99 DestroyJavaVM main 5 RUNNABLE 0 0:39 false false
4 Signal Dispatcher system 9 RUNNABLE 0 0:0 false true
19 grpc-default-worker-ELG-1-1 main 5 RUNNABLE 0 0:0 false true
21 grpc-default-worker-ELG-1-2 main 5 RUNNABLE 0 0:0 false true
97 http-nio-11003-Acceptor main 5 RUNNABLE 0 0:0 false true
85 http-nio-11003-BlockPoller main 5 RUNNABLE 0 0:0 false true
96 http-nio-11003-ClientPoller main 5 RUNNABLE 0 0:0 false true
54 lettuce-nioEventLoop-4-1 main 5 RUNNABLE 0 0:0 false true
70 lettuce-nioEventLoop-4-2 main 5 RUNNABLE 0 0:0 false true
36 nioEventLoopGroup-3-1 system 10 RUNNABLE 0 0:0 false false
42 nioEventLoopGroup-3-2 system 10 RUNNABLE 0 0:0 false false
37 nioEventLoopGroup-4-1 system 10 RUNNABLE 0 0:0 false false
Affect(row-cnt:0) cost in 120 ms.
3000+线程处于等待状态,现在我选择一个随机等待线程池线程,如下所示:
[arthas@1]$ thread 4410
"pool-96-thread-10" Id=4410 WAITING on java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject@3e27c029
at sun.misc.Unsafe.park(Native Method)
- waiting on java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject@3e27c029
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:1074)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Affect(row-cnt:0) cost in 16 ms.
但问题是,我不知道线程是从哪里开始的,是什么导致等待线程增加的。有没有办法找出从哪里开始线程或为什么等待线程增加?我现在使用的是Java ThreadExecutor。现在等待线程是由6000+决定的。我添加了一个自定义配置:
@Configuration
public class ScheduleConfig implements SchedulingConfigurer {
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.setScheduler(Executors.newScheduledThreadPool(30));
}
}
发布于 2020-09-24 16:06:57
您所显示的堆栈跟踪是“状态正常”:这是一个线程池执行器线程,可以完成工作,但是工作队列是空的。在这种情况下,‘等待’的意思是:我在等待一份工作,而不是:“我有事情要做,但不能做,因为我在等待事情先完成”。
现在,3000条线程本身就有些问题;每个线程都有自己的堆栈空间。它的大小取决于您的-Xss
参数,但它们往往从64k到1MB。如果是1MB,那就是.3GB的堆栈空间,那是.次优在VM升温之后,这个数字(等待作业的线程数量)也不应该增加太多。
如果所有/大多数等待线程都有类似的跟踪,那么实际上只有两个选项:
执行者背后的想法是,你只做一个,或者至少很少。
如果您必须在运行中的应用程序中创建它们(相对于正常情况,即创建作业并将其提供给单例执行器),那么要注意它们实际上是资源:如果您不“关闭”它们,则您的流程将需要越来越多的资源,直到VM最终耗尽时崩溃为止。
要关闭它们,您可以调用shutdown()
(它请求得很好)和shutdownNow()
(它更有进攻性,并且将永远取消尚未拾取的任务)。
因此,简单地说:
new ScheduledThreadPoolExecutor
并检查情况。如果您必须在action..shutdown()
会完成任务的。https://stackoverflow.com/questions/64049987
复制相似问题