.net 线程与线程池

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/230003/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 10:24:47  来源:igfitidea点击:

Thread vs ThreadPool

.netmultithreadingarchitecturethreadpool

提问by Mark Ingram

What is the difference between using a new thread and using a thread from the thread pool? What performance benefits are there and why should I consider using a thread from the pool rather than one I've explicitly created? I'm thinking specifically of .NET here, but general examples are fine.

使用新线程和使用线程池中的线程有什么区别?有什么性能优势,为什么我应该考虑使用池中的线程而不是我明确创建的线程?我在这里专门考虑 .NET,但一般示例都很好。

采纳答案by Karg

Thread pool will provide benefits for frequent and relatively short operations by

线程池将为频繁且相对较短的操作提供好处

  • Reusing threads that have already been created instead of creating new ones (an expensive process)
  • Throttling the rate of thread creation when there is a burst of requests for new work items (I believe this is only in .NET 3.5)

    • If you queue 100 thread pool tasks, it will only use as many threads as have already been created to service these requests (say 10 for example). The thread pool will make frequent checks (I believe every 500ms in 3.5 SP1) and if there are queued tasks, it will make one new thread. If your tasks are quick, then the number of new threads will be small and reusing the 10 or so threads for the short tasks will be faster than creating 100 threads up front.

    • If your workload consistently has large numbers of thread pool requests coming in, then the thread pool will tune itself to your workload by creating more threads in the pool by the above process so that there are a larger number of thread available to process requests

    • check Herefor more in depth info on how the thread pool functions under the hood

  • 重用已经创建的线程而不是创建新线程(一个昂贵的过程)
  • 当对新工作项的请求激增时,限制线程创建的速度(我相信这仅在 .NET 3.5 中)

    • 如果您将 100 个线程池任务排队,它只会使用与已创建的线程一样多的线程来为这些请求提供服务(例如 10 个)。线程池会进行频繁的检查(我相信在 3.5 SP1 中每 500 毫秒一次),如果有排队的任务,它将创建一个新线程。如果您的任务很快,那么新线程的数量将很少,并且将 10 个左右的线程重用于短任务比预先创建 100 个线程要快。

    • 如果您的工作负载始终有大量线程池请求传入,则线程池将通过上述过程在池中创建更多线程来调整自身以适应您的工作负载,以便有更多线程可用于处理请求

    • 检查此处了解有关线程池如何在后台运行的更多详细信息

Creating a new thread yourself would be more appropriate if the job were going to be relatively long running (probably around a second or two, but it depends on the specific situation)

如果作业的运行时间相对较长(可能大约一两秒钟,但这取决于具体情况),自己创建一个新线程会更合适

@Krzysztof - Thread Pool threads are background threads that will stop when the main thread ends. Manually created threads are foreground by default (will keep running after the main thread has ended), but can be set to background before calling Start on them.

@Krzysztof - 线程池线程是后台线程,会在主线程结束时停止。手动创建的线程默认为前台(在主线程结束后将继续运行),但可以在对它们调用 Start 之前将其设置为后台。

回答by Martin

The .NET managed threadpool: -

.NET 托管线程池:-

  • Sizes itself based on the current workload and available hardware
  • Contains worker threads andcompletion port threads (which are specifically used to service IO)
  • Is optimised for a large number of relatively short-lived operations
  • 根据当前工作负载和可用硬件调整自身大小
  • 包含工作线程完成端口线程(专门用于服务IO)
  • 针对大量相对短暂的操作进行了优化

Other thread pool implementations exist that might be more appropriate for long-running operations.

其他线程池实现可能更适合长时间运行的操作。

Specifically, use a thread pool to prevent your app from creating too manythreads. The most important feature of a threadpool is the work queue. That is, once your machine is sufficiently busy, the threadpool will queue up requests rather than immediately spawn more threads.

具体来说,使用线程池来防止您的应用程序创建过多线程。线程池最重要的特性是工作队列。也就是说,一旦您的机器足够忙,线程池就会将请求排队,而不是立即产生更多线程。

So, if you will create a small, bounded number of threads create them yourself. If you cannot determine up-front how many threads might be created (e.g. they're created in response to incoming IO), and their work will be short-lived, use the threadpool. If you don't know how many, but their work will be long-running, there's nothing in the platform to help you - but you might be able to find alternative threadpool implementations that fit.

因此,如果您要创建少量有限数量的线程,请自行创建它们。如果您无法预先确定可能创建多少线程(例如,它们是为响应传入的 IO 而创建的),并且它们的工作将是短暂的,请使用线程池。如果您不知道有多少,但他们的工作将长期运行,则平台中没有任何内容可以帮助您 - 但您或许可以找到适合的替代线程池实现。

回答by Martin

also

new Thread().Start()

new Thread().Start()

spawns Foreground thread that will not die if you close your program. ThreadPool threads are background threads that die when you close the app.

产生前台线程,如果您关闭程序,该线程不会死。ThreadPool 线程是在您关闭应用程序时死亡的后台线程。

回答by PeterM

I was curios about the relative resource usage for these and and ran a benchmark on my 2012 dual-core Intel i5 laptop using .net 4.0 release build on windows 8. Thread Pools took on average 0.035ms to start where Threads took an average of 5.06ms. In other words Thread in the pool started about 300x faster for large numbers of short lived threads. At least in the tested range (100-2000) threads, the total time per thread seemed pretty constant.

我对这些的相对资源使用情况感到好奇,并在我的 2012 双核 Intel i5 笔记本电脑上使用 .net 4.0 版本在 Windows 8 上运行了一个基准测试。线程池平均需要 0.035 毫秒才能启动,而线程平均需要 5.06多发性硬化症。换句话说,对于大量短期线程,池中的线程启动速度大约快 300 倍。至少在测试范围 (100-2000) 个线程中,每个线程的总时间似乎相当稳定。

This is the code that was benchmarked:

这是经过基准测试的代码:

    for (int i = 0; i < ThreadCount; i++) {
        Task.Run(() => { });
    }

    for (int i = 0; i < ThreadCount; i++) {
        var t = new Thread(() => { });
        t.Start();
    }

enter image description here

在此处输入图片说明

回答by biozinc

Check here for an earlier thread:

在此处查看较早的线程:

When should I not use the ThreadPool in .Net?

我什么时候不应该在 .Net 中使用 ThreadPool?

Summary is that Threadpool is good if you need to spawn many shortlived threads, whereas using Threads gives you a bit more control.

总结是,如果您需要生成许多短命的线程,则 Threadpool 是很好的,而使用 Threads 可以给您更多的控制权。

回答by Rob Prouse

If you need a lot of threads, you probably want to use a ThreadPool. They re-use threads saving you the overhead of thread creation.

如果您需要很多线程,您可能想要使用 ThreadPool。它们重用线程,从而节省了线程创建的开销。

If you just need one thread to get something done, Thread is probably easiest.

如果你只需要一个线程来完成某件事,线程可能是最简单的。

回答by MSalters

Thread local storage is not a good idea with thread pools. It gives threads an "identity"; not all threads are equal anymore. Now thread pools are especially useful if you just need a bunch of identical threads, ready to do your work without creation overhead.

线程本地存储对于线程池来说不是一个好主意。它给线程一个“身份”;并非所有线程都不再相同。现在,如果您只需要一堆相同的线程,准备好在没有创建开销的情况下完成您的工作,则线程池特别有用。

回答by supercat

The primary need for theadpool threads is to handle short little tasks that are expected to complete almost instantly. Hardware interrupt handlers often run in a stacking context which would not be suitable for non-kernel code, but a hardware interrupt handler may discover that a user-mode I/O completion callback should be run as soon as possible. Creating a new thread for the purpose of running such a thing would be massive overkill. Having a few pre-created threads which can be dispatched to run I/O completion callbacks or other similar things is much more efficient.

theadpool 线程的主要需求是处理预计几乎立即完成的短小任务。硬件中断处理程序通常在不适合非内核代码的堆栈上下文中运行,但硬件中断处理程序可能会发现应尽快运行用户模式 ​​I/O 完成回调。为运行这样的事情而创建一个新线程将是巨大的矫枉过正。有一些预先创建的线程可以被调度来运行 I/O 完成回调或其他类似的事情,效率更高。

A key aspect of such threads is that if I/O completion methods always complete essentially instantaneously and never block, and the number of such threads that are presently running such methods is at least equal to the number of processors, the only way any other thread could run before one of the aforementioned methods finishes would be if one of the other methods blocks or its execution time exceeds a normal threading time-slice; neither of those should happen very often if the thread pool is used as intended.

此类线程的一个关键方面是,如果 I/O 完成方法总是基本上立即完成并且从不阻塞,并且当前运行此类方法的此类线程的数量至少等于处理器的数量,这是任何其他线程的唯一途径如果其他方法之一阻塞或其执行时间超过正常线程时间片,则可以在上述方法之一完成之前运行;如果按预期使用线程池,这两种情况都不应该经常发生。

If a method cannot be expected to exit within 100ms or so of when it starts execution, the method should be executed via some means other than the main thread pool. If one has a lot of tasks to perform which are CPU intensive but won't block, it may be helpful to dispatch them using a pool of application threads (one per CPU core) which is separate from the "main" threadpool, since using more threads than cores will be counterproductive when running non-blocking CPU-intensive tasks. If, however, a method will take a second or longer to execute, and will spend most of its time blocked, the method should likely be run in a dedicated thread, and should almost certainly not be run in a main-threadpool thread. If a long-running operation needs to be triggered by something like an I/O callback, one should either start a thread for the long-running operation in advance of the callback and have it wait on a monitor which the callback pulses, or else have the callback launch a new thread to perform the operation while the callback exits, effectively returning its own thread to the threadpool.

如果一个方法不能在开始执行后的 100 毫秒左右退出,则应该通过主线程池以外的其他方式执行该方法。如果要执行大量 CPU 密集型但不会阻塞的任务,则使用与“主”线程池分开的应用程序线程池(每个 CPU 内核一个)调度它们可能会有所帮助,因为使用在运行非阻塞 CPU 密集型任务时,线程数多于内核数会适得其反。但是,如果一个方法需要一秒钟或更长时间来执行,并且大部分时间都被阻塞,则该方法应该在专用线程中运行,并且几乎肯定不应该在主线程池线程中运行。如果需要通过 I/O 回调之类的东西触发长时间运行的操作,

回答by Seyedraouf Modarresi

Thread:

主题

  1. Creating a Thread is far slower than using Thread-pool.
  2. You can change the priority of a thread.
  3. The max number of threads in a process related to resources.
  4. Thread is at the OS level and controlled by OS.
  5. Using Thread is a better option when the task is relatively long-running
  1. 创建线程比使用线程池慢得多。
  2. 您可以更改线程的优先级。
  3. 进程中与资源相关的最大线程数。
  4. 线程处于操作系统级别并由操作系统控制。
  5. 当任务运行时间相对较长时,使用 Thread 是更好的选择

Thread-Pool:

线程池

  1. Running a Thread on thread-pool is far faster than directly creating a Thread.
  2. You can not change the priority of a thread run based on Thread-pool.
  3. There is only one Thread-pool per process.
  4. The Thread-pool is managed by CLR.
  5. The Thread-pool is useful for short-lived operation.
  6. The numbers of Threads in Thread-pool is related to the application load.
  7. TPL tasks run based on Thread-pool
  1. 在线程池上运行线程比直接创建线程要快得多。
  2. 您不能更改基于线程池的线程运行的优先级。
  3. 每个进程只有一个线程池。
  4. 线程池由 CLR 管理。
  5. 线程池对于短期操作很有用。
  6. 线程池中的线程数与应用负载有关。
  7. 基于线程池运行的 TPL 任务

回答by Robin

In general (I have never used .NET), a thread pool would be used for resource management purposes. It allows constraints to be configured into your software. It also may be done for performance reasons, as creation of new threads may be costly.

通常(我从未使用过 .NET),线程池将用于资源管理目的。它允许将约束配置到您的软件中。也可能出于性能原因而这样做,因为创建新线程的成本可能很高。

There may also be system specific reasons. In Java (again I don't know if this applies to .NET), the manager of the threads may apply thread specific variables as each thread is pulled from the pool, and unset them when they are returned (common way to pass something like an identity).

也可能有系统特定的原因。在 Java 中(同样我不知道这是否适用于 .NET),线程管理器可能会在每个线程从池中拉出时应用线程特定的变量,并在返回时取消设置它们(传递类似的常用方法)身份)。

Example constraint: I only have 10 db connections, so I would only allow 10 worker threads for accessing the database.

示例约束:我只有 10 个数据库连接,所以我只允许 10 个工作线程访问数据库。

This doesn't mean that you should not create your own threads, but there are conditions under which it makes sense to use a pool.

这并不意味着您不应该创建自己的线程,但是在某些条件下使用池是有意义的。