关于创建线程或使用线程池处理100个任务

15
我正在创建一个监视应用程序,可以监视100-150个设备...现在为了设计监视应用程序,我有两种方法:-
  1. 为要监视的每个设备创建一个线程,每个线程会ping(使用ICMP)设备以知道设备是否在线。这些线程将无限运行以在特定时间间隔(比如60秒)后了解它们的状态。
  2. 创建一个线程池,并为每个设备提交一个任务到线程池中。任务很简单,就是ping设备。因此,在当前设计中,任务的数量将超过线程池中的线程数。例如,假设有100个要监视的设备,则将有100个任务需要监视,而线程池将拥有40个线程来完成这100个任务。当然,运行下一批任务的时间持续时间将为完成线程池中所有待处理任务而设计。
哪种方法更好?
4个回答

12
我会创建一个ScheduledExecutorService(例如通过Executors.newScheduledThreadPool),让您可以安排重复的ping。您知道每个ping需要多长时间吗?如果您只需要每分钟ping 100个设备一次,我希望您只需要很少的线程-远远少于40个。
您可以使用相对较小的线程数启动它,但请注意Mark Peters在评论中提出的信息-所使用的实现不会扩展(正如我所期望的那样);它实际上是一个固定的线程池。尽管如此,您应该能够做到少于40个线程...

1
这也是我的建议。我也有同样的担忧...如果N个设备同时离线,而N大于线程池大小...监控可能会出现饥饿的情况。如果能够实现一个ScheduledExecutorService的版本,它可以检测到任务被饥饿并相应地增加线程池大小,那将非常棒。 - Mark Peters
如果您添加一些最小的诊断功能(例如通过JMX),您将能够监控进程并相应地进行调整。使用执行器服务要比自己手动创建线程池或个别线程容易得多。 - David Harkness
1
我只是在ScheduledThreadPoolExecutor的文档中查看了一下:尽管此类继承自ThreadPoolExecutor,但它并不适用于继承的某些调整方法。特别是因为它作为一个使用corePoolSize线程和无界队列的固定大小池,所以对maximumPoolSize的调整没有有用的效果。虽然这会很好! - Mark Peters
1
我正在使用Java的InetAddress类来ping设备。所以最多等待5秒钟进行ping。请参见代码:- InetAddress addr = InetAddress.getByName(HOST);如果(addr.isReachable(5000))返回true; - ashishgupta_mca
1
@ashishgupta_mca:好的,所以每个线程每分钟至少可以ping 12个设备,因此10个线程应该足够了。而且这是最坏的情况... - Jon Skeet
显示剩余3条评论

2
为每个设备创建一个单独的线程不是可扩展的解决方案。想象一下,如果您的解决方案必须处理越来越多的设备,从100个到1000个;您不能每次都生成一个单独的线程。
创建线程池将是一个理想的解决方案。您可以根据需求和资源可用性调整线程池的大小。如果您需要定期基于固定时间间隔对设备进行ping,则可以使用计划执行器服务,它在内部负责定期安排任务。但是,使用线程池是显而易见的选择。

2
当计算最大线程数时,应考虑ping超时。如果ping超时为5秒,重复周期为60秒,需要多少个线程才能ping 100个设备?
每个线程在60秒内可以进行12次设备ping(60秒允许12次ping在5秒后超时)。这意味着您需要至少9个线程,每个线程每60秒执行12次ping。
numberOfThreads = numberOfDevices / (pollingPeriod/pingTimeout) = 100 / (60/5) = 100/12 = 9 threads

1
这与Jon的答案很相符。实际数据是最长等待5秒,周期60秒。因此,您需要查看8-9个线程以确保可以处理100个设备。但是,如果所有设备在时间0注册并且第一次测试从时间60开始,则许多设备可能直到时间115(仅第一次)才会被ping到。 - Mark Peters

1
我建议使用线程池而不是为每个设备创建一个新线程。线程池适用于许多短时间任务,你的问题完全符合这一点。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接