sockets Java线程池与高请求场景中的新线程
我有一些关于REST服务的旧java代码,它对每个传入的请求使用单独的线程。也就是说,主回路将在插座上循环。accept()并将socket交给Runnable,然后Runnable将启动自己的后台线程并调用run on自身。这在一段时间内运行良好,直到最近我才注意到,在高负载情况下,接受处理请求的延迟是不可接受的。当我说令人钦佩地好时,我的意思是它每秒处理100-200个请求,没有显著的CPU使用率。只有在其他守护进程也添加负载时,性能才会下降,并且只有在负载超过5时才会下降。当机器处于其他过程组合的高负载(5-8)下时,从接受到处理的时间会高得离谱(500毫秒到3000毫秒),而实际处理时间则保持在10毫秒以下。这些都在双核centos 5系统上
已经习惯了在网络上使用线程池。NET,我认为线程创建是罪魁祸首,我想我会在java中应用相同的模式。现在我的Runnable是用ThreadPool执行的。Executor(池使用和ArrayBlockingQueue)。同样,它在大多数情况下都非常有效,除非机器负载很高,否则从创建runnable到调用run()的时间也会显示出同样荒谬的时间。但更糟糕的是,在线程池逻辑就绪的情况下,系统负载几乎翻了一番(10-16)。所以现在我在负载加倍的情况下遇到了同样的延迟问题
我的怀疑是,队列的锁争用比之前没有锁的新线程启动成本更糟糕。任何人都可以分享他们的经验,新线程与线程池。如果我的怀疑是正确的,那么有人有其他方法来处理线程池而不存在锁争用吗
我很想让整个系统成为单线程,因为我不知道线程有多大帮助,IO似乎也不是问题,但我确实收到了一些长期存在的请求,这些请求会阻止一切
谢谢, 阿恩
更新:我切换到了Executors.newFixedThreadPool(100);
,虽然它保持了相同的处理能力,但负载几乎立即翻了一番,运行12小时后,负载始终保持在2倍。我猜在我的情况下,每个请求一个新线程更便宜
# 1 楼答案
测量,测量,测量!它在哪里消磨时间?创建Runnable时会发生什么?Runnable在实例化过程中是否存在阻塞或延迟的情况?延迟期间发生了什么
事实上,我非常相信从总体上考虑问题,但这种情况下,像这样的意外行为,只需要有一些测量
运行时环境、JVM版本和体系结构是什么