【问题标题】:Limit number of concurrent thread in a thread pool限制线程池中的并发线程数
【发布时间】:2013-08-19 09:36:44
【问题描述】:

在我的代码中,我有一个循环,在这个循环中,我向远程 Web 服务发送了几个请求。 WS 提供商说:“网络服务最多可以托管 n 个线程”,所以我需要限制我的代码,因为我无法发送 n+1 个线程。

如果我要发送 m 个线程,我会立即执行第一个 n 个线程,并且一旦其中一个线程完成,一个新线程(其中一个剩余的 m-n 个线程)将被执行,以此类推,直到所有 m 个线程都被执行。

我想到了Thread Poolexplicit setting of the max thread number to n。够了吗?

【问题讨论】:

  • 为什么不包装整个 for 循环,以便单个后台线程池线程执行整个循环。这样您就不必担心线程创建等。
  • 您真的是该 Web 服务的唯一用户吗?不寻常。

标签: multithreading threadpool


【解决方案1】:

为此,我会避免使用多个线程。相反,将整个循环包装起来,可以在单个线程上运行。但是,如果您确实想使用 /a 线程池启动多个线程,那么我将使用 Semaphore 类来促进所需的线程限制;方法如下...

信号量就像一个普通的夜总会保镖,它已经提供了一个俱乐部容量,并且不允许超过这个限制。一旦俱乐部坐满了,就没有其他人可以进入了……外面已经排起了长队。然后当一个人离开时,另一个人可以进入(感谢 J. Albahari 的类比)。

值为 1 的 Semaphore 等效于 MutexLock,除了 Semaphore 没有所有者,因此它是线程无知的。任何线程都可以在Semaphore 上调用Release,而对于Mutex/Lock,只有获得Mutex/Lock 的线程才能释放它。

现在,对于您的情况,我们可以使用Semaphores 来限制并发并防止太多线程同时执行特定的一段代码。在下面的示例中,五个线程尝试进入一个只允许三个人进入的夜总会......

class BadAssClub
{
    static SemaphoreSlim sem = new SemaphoreSlim(3);
    static void Main()
    {
        for (int i = 1; i <= 5; i++) 
            new Thread(Enter).Start(i);
    }

    // Enfore only three threads running this method at once.
    static void Enter(int i)
    {
        try
        {
            Console.WriteLine(i + " wants to enter.");
            sem.Wait();
            Console.WriteLine(i + " is in!");
            Thread.Sleep(1000 * (int)i);
            Console.WriteLine(i + " is leaving...");
        }
        finally
        {
            sem.Release();
        }
    }
}

我希望这会有所帮助。


编辑。您也可以使用ThreadPool.SetMaxThreads 方法。此方法限制允许在线程池中运行的线程数。但它为线程池本身“全局”执行此操作。这意味着如果您在应用程序使用的库中运行 SQL 查询或其他方法,那么新线程将不会因为这种阻塞而启动。这可能与您无关,在这种情况下使用SetMaxThreads 方法。但是,如果您想阻止特定方法,使用Semphores 会更安全。

【讨论】:

  • 是的,这有帮助!你能解释一下 ThreadPool.SetMaxThreads 方法的用途吗?谢谢你:)
  • PS:一个线程不会那么有用。导致 WS 响应花费大量时间,幸运的是 WS 针对多个实例进行了优化,因此多个线程将完成这项工作!
  • 设置可以并发活动的线程池的请求数。在线程池线程可用之前,所有高于该数量的请求都会排队。更改线程池中的最大线程数时要小心。虽然您的代码可能会受益,但更改可能会对您使用的代码库产生不利影响。将线程池大小设置得太大会导致性能问题。如果同时执行的线程太多,任务切换开销就成为一个重要因素。
  • 我已经阅读了该文档,我只是想知道“可以同时活动的线程池的请求数”是否与我的意思相同,如果这是真的:使用这种方法直接避免信号量。
  • 是的,这个方法限制了线程池中允许运行的线程数。但正如上述评论的第二部分所述,它为线程池本身“全局”执行此操作。这意味着如果您在应用程序使用的库中运行 SQL 查询或其他方法,那么新线程将不会因为这种阻塞而启动。这可能与您无关,在这种情况下使用SetMaxThreads 方法。但是,如果您想阻止特定方法,使用Semphores 会更安全...干杯。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-14
  • 2015-02-12
  • 2015-07-17
  • 2013-01-17
  • 2019-01-29
相关资源
最近更新 更多