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

Posted

技术标签:

【中文标题】执行器服务或守护线程哪个更适合多线程?【英文标题】:Executor service or daemon threads which is better for multi threads? 【发布时间】:2018-06-13 05:21:47 【问题描述】:

抱歉,编辑太长了,

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

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);

可以在服务器上使用相同的方法进行负载测试吗?

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

提前致谢!

【问题讨论】:

您研究过常规线程和守护线程之间的区别吗?你学到了什么? @JimGarrison 是的,我做了一些研究,我创建守护线程的原因是为了更快地创建更多与服务器的连接。 您为什么认为守护线程创建速度更快或允许更多连接到服务器? @JimGarrison 更快我的意思是说我正在从 100k url 下载数据并且 run 方法有数据下载的代码,现在如果我使用执行器服务下载我只能下载一个 url时间,但如果我使用守护线程,我可以创建/下载多个下载连接。 抱歉,这些都没有任何意义。 ExecutorService 可以设置为并行运行多个线程。 【参考方案1】:

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

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

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

【讨论】:

在很多方面我的问题不是我想问的(不知道为什么),但你的回答正是我想要的......谢谢:)【参考方案2】:

守护线程是在所有其他线程完成后不阻止 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 

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

【讨论】:

【参考方案3】:

负载测试不仅仅是用请求“锤击”您的服务器,表现良好的负载测试需要使用真实浏览器代表真实用户以及所有相关内容,例如:

headers cookies cache 处理嵌入式资源(图像、脚本、样式、字体)

所以我建议使用专门的load testing tool,它能够尽可能接近地代表真实用户并自动处理上述问题。通常负载测试工具还允许您设置rendezvous points 并提供大量指标和图表,以便您能够查看连接时间、网络延迟、吞吐量、将增加的负载与增加的响应时间/错误数量等相关联。

【讨论】:

以上是关于执行器服务或守护线程哪个更适合多线程?的主要内容,如果未能解决你的问题,请参考以下文章

threading模块—Python多线程编程

Java多线程-线程的优先级(priority)以及守护线程(daemon)

python 并发编程 多线程 守护线程

并发编程之多线程基础-守护线程与非守护线程

Java 多线程之守护线程(Daemon)

多线程