我有一个main方法,它使用一个核心池大小为75的ScheduledExecutorService来为每个总共50,000个用户计划运行15个操作:
Lists.partition(users, 100).stream()
.forEach(batchOfUsers -> batchOfUsers
.parallelStream().forEach(scheduleKickingOffActions));
scheduleKickingOffActions
让用户使用不同的可运行操作和任意延迟调用scheduledExecutor.schedule(Runnable, delay)
15次。
这是一个相当繁重的计划,有很多事情要做。随着主线程与批次的进行,计划开始启动并执行操作。当每个计划的行动开始时,它会以另一个任意延迟重新安排自己。因此,每个用户反复运行他的每个动作。
查看scheduleKickingOffActions
内的日志记录语句,我注意到负责运行上述代码片段的主线程在某些时候停止,同时安排这些用户'活动。该点的范围从第4000个用户到第400个用户。它似乎忘了忘记'完成任务。
我不能很好地解释为什么会发生这种情况,我只能想象,当ScheduledExecutorService中的计划任务启动时,他们设法抢占主线程..
我还有进一步的证据表明我的主要线程已完全消失。在批处理代码之后,我有一个睡眠声明:
Thread.sleep(360);
之后我做了:
scheduledExecutor.shutdownNow();
scheduledExecutor.awaitTermination(1, TimeUnit.HOURS);
System.out.println("\nFinished.\n");
stopwatch.stop();
System.out.println("Total time elapsed - " + stopwatch.elapsed(TimeUnit.SECONDS) + " seconds");
System.exit(0);
强制程序运行6个小时。这些语句都没有打印出来,我的程序一直运行超过6小时标记,直到我从Ctrl + C出来。显然,主要线程在批处理工作期间的某个时刻被抛弃,并且永远不会进一步发展。
我没有在输出和日志中看到任何异常,并且计划的任务都按预期工作,并且所有任务都按预期重新安排。
拥有更多Java专业知识的人是否愿意分享他们对此的看法?是否有太多线程在同一时间工作?我希望主线程能够在某个时刻返回它的任务。