python 为啥不建议用threadpool

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python 为啥不建议用threadpool相关的知识,希望对你有一定的参考价值。

参考技术A IDLE是py原生自带的迷你IDE(只能算迷你),而win的powershell,以及*nix跟mac的terminal不是IDE!是shell,是cli!先搞清楚IDE跟shell或cli的区别。
你这个回答你的是:不要用任何IDE,要用shell加随便一个文本编辑器,来开始学。
至于什么时候开始过渡到IDE,我觉得是码到大概200行以上~才需要
另外什么缩进代码高亮的,你发的教程里也用上了n++这类富编辑器,这根本不是问题。本回答被提问者采纳
参考技术B 谁说不建议用threadpool的 虽然python的多线程在GIL下是个鸡肋 但对于IO密集型的应用 多线程还是可以提高效率的 CPU密集型就算了吧

为啥使用 ThreadPool 检查代理比不使用 ThreadPool 需要更多时间?

【中文标题】为啥使用 ThreadPool 检查代理比不使用 ThreadPool 需要更多时间?【英文标题】:Why checking proxies with ThreadPool takes much more time than doing the same without ThreadPool?为什么使用 ThreadPool 检查代理比不使用 ThreadPool 需要更多时间? 【发布时间】:2012-06-12 14:08:37 【问题描述】:

使用 this 帖子我编写了检查 200 个代理的代码。套接字的超时时间为 2 秒。一切正常,但问题是 Code #1 需要超过 2 分钟才能检查 200 个代理,限制为 2 秒超时。但是使用 Code #2 检查 200 个代理需要 2 秒,而使用 Code #2 检查 1000 个代理也需要 2 秒。

代码 #1 使用线程池。 代码 #1 打开 proxyCount 套接字,进入休眠状态 2 秒,然后检查成功的情况。正好需要 2 秒。

那么,代码 #1 中的问题在哪里?为什么至少有 20 个线程的 ThreadPool 比没有线程的要慢得多?

代码 #1

int proxyCount = 200;  
CountdownEvent cde = new CountdownEvent(proxyCount);     
private void RefreshProxyIPs(object obj)
     
    int workerThreads, ioThreads;
    ThreadPool.GetMinThreads(out workerThreads, out ioThreads);
    ThreadPool.SetMinThreads(20, ioThreads);

    var proxies = GetServersIPs(proxyCount);
    watch.Start();
    for (int i = 0; i < proxyCount; i++)
    
        var proxy = proxies[i];
        ThreadPool.QueueUserWorkItem(CheckProxy, new IPEndPoint(IPAddress.Parse(proxy.IpAddress), proxy.Port));
    
    cde.Wait();
    cde.Dispose();
    watch.Stop();


private List<IPEndPoint> list = new List<IPEndPoint>();
private void CheckProxy(object o)

     var proxy = o as IPEndPoint;
     using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
     
         var asyncResult = socket.BeginConnect(proxy.Address, proxy.Port, null, null);
         if (asyncResult.AsyncWaitHandle.WaitOne(2000))
         
             try
             
                 socket.EndConnect(asyncResult);
             
             catch (SocketException)
             
             
             catch (ObjectDisposedException)
             
             
         
         if (socket.Connected)
         
             list.Add(proxy);
             socket.Close();
         
     
     cde.Signal();

代码 #2

int proxyCount = 200;
var sockets = new Socket[proxyCount];
var socketsResults = new IAsyncResult[proxyCount];
var proxies = GetServersIPs(proxyCount);
for (int i = 0; i < proxyCount; i++)

      var proxy = proxies[i];
      sockets[i] = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
      socketsResults[i] = sockets[i].BeginConnect(IPAddress.Parse(proxy.IpAddress), proxy.Port, null, proxy);             

Thread.Sleep(2000);
for (int i = 0; i < proxyCount; i++)

     var success = false;
     try
     
         if (socketsResults[i].IsCompleted)
         
              sockets[i].EndConnect(socketsResults[i]);
              success = sockets[i].Connected;
              sockets[i].Close();
         

         sockets[i].Dispose();
     
     catch  

     var proxy = socketsResults[i].AsyncState as Proxy;
     if (success)   _validProxies.Add(proxy); 

【问题讨论】:

【参考方案1】:

您启动的线程池线程不是很好的 tp 线程。他们不执行任何实际工作,只是阻止 WaitOne() 调用。所以其中 20 个立即开始执行,并且在 2 秒内没有完成。线程池调度程序只允许另一个线程在其中一个线程完成或 none 在 0.5 秒内完成时启动。然后它允许额外的一个运行。因此,所有请求都需要一段时间才能完成。

您可以通过调用 SetMinThreads() 并将最小值设置为 200 来修复它。但这非常浪费系统资源。您不妨调用 Socket.BeginConnect() 200 次,然后找出 2 秒后发生的事情。您的快速版本。

【讨论】:

你说的完全正确,但是 Code #1 需要超过 2 分钟才能执行。 20-30 秒 - 好的,但是 2 分钟。你知道为什么会这样吗? 至少为 1.5 分钟,180 x 0.5 秒。被监视的水壶需要更长的时间才能煮沸。 20 个线程在同一时间,每个 2 秒,所以我的计算给我 200(代理)/20(线程)* 2(每个秒)= 20 秒 您错过了我试图解释的内容,TP 调度程序仅允许在运行的线程未在 1/2 秒内完成时启动 extra 线程。 @Hans,你是怎么计算出来的? 180号是什么意思?【参考方案2】:

在第一个示例中,您正在等待每个代理连接超时或 2 秒,以先到者为准。另外,您正在排队 200 个单独的工作请求。您的线程池大小可能会比这小得多。使用GetMaxThreads 进行检查。您只会同时运行该数量的工作请求,并且下一个请求必须等待前一个项目超时。

【讨论】:

以上是关于python 为啥不建议用threadpool的主要内容,如果未能解决你的问题,请参考以下文章

枚举很好用啊!为啥阿里不建议返回值用枚举??

枚举很好用啊!为啥阿里不建议返回值用枚举??

为啥不建议用 try catch

为啥python有两个不同的版本,并且语法规范啥的都不相通呢?

为啥以前我那个oppo手机可以用vsco这个软件,怎么现在这个oppo手机不可以用了呢

谷歌浏览器直接提取的xpath,在python中为啥无法提取相应内容