执行器服务或守护进程线程哪个更适合多线程?



抱歉编辑时间过长,

我正在尝试下载 100k 网址,我开始使用执行器服务下载,如下所示,

ExecutorService executorService = Executors.newFixedThreadPool(100);
for (int i = 0; i < list.size(); i++) {
try {
Callable callable = new Callable() {
public List<String> call() throws Exception {
//http connection
}
};
Future future = executorService.submit(callable);

但是上述方法是一次只下载一个URL..

所以我尝试创建守护程序线程(如下所示(,并且此方法创建了多个下载连接(如预期的那样(。

for(int i=0; i<10; i++) {
Thread t = new Thread("loadtest " + i);
t.setDaemon(true);
t.start();
}
while(true) {
boolean flag = true;
Set<Thread> threads = Thread.getAllStackTraces().keySet();
for(Thread t : threads) {
if(t.isDaemon() && t.getName().startsWith("loadtest")) {
flag = false;
break;
}
}
if(flag)
break;
Thread.sleep(5000);
}

是否可以将相同的方法用于服务器上的负载测试?

关于如何进行负载测试的任何其他建议也将有很大帮助。

提前感谢!

我会冒险猜测您的ExecutorService不起作用,因为您在循环中返回的Future实例上调用get()。此错误确实会导致您的处理被序列化,就好像您只有一个线程一样,因为在第一个任务完成之前不会提交另一个任务。

如果您确实需要使用Callable,请不要get()结果,直到您准备好在任务完成时无限期阻止 - 如果尚未提交,则无法完成。对于下载 URL,最好使用Runnable,其中主线程提交 URL,然后忘记任务;任务可以独立完成其 URL 的处理。

如果您快速生成新任务,则可能会排队太多,以至于内存不足。在这种情况下,可以使用有界队列并直接使用ThreadPoolExecutor设置适当的拒绝处理程序。

守护进程线程是一个线程,当所有其他线程完成时,它不会阻止 JVM 退出。

我相信如果你想等到守护进程线程没有完成的时候,那么我建议不要使用守护进程线程,因为它不应该用于该用例。 您可以使用Thread#join来等待主线程。

for(int i=0; i<10; i++) {
Thread t = new Thread("loadtest " + i);
t.setDaemon(true);
t.start();
t.join(); // main or parent thread will wait util the child thread finished 
}

我相信在您的用例中,您应该使用普通线程而不是守护程序。

负载测试不仅仅是用请求"锤击"你的服务器,行为良好的负载测试需要使用真实的浏览器来表示真实的用户,以及所有相关的东西,如:

  • 饼干
  • 缓存
  • 处理嵌入式资源(图像、脚本、样式、字体(

因此,我建议使用专门的负载测试工具,该工具能够尽可能接近地表示真实用户并自动处理上述要点。此外,负载测试工具通常允许您设置集合点并提供大量指标和图表,以便您能够看到连接时间、网络延迟、吞吐量、增加负载与增加响应时间/错误数量等。

最新更新