天道酬勤,学无止境

Thread Pool vs Many Individual Threads

I'm in the middle of a problem where I am unable decide which solution to take.

The problem is a bit unique. Lets put it this way, i am receiving data from the network continuously (2 to 4 times per second). Now each data belongs to a different, lets say, group. Now, lets call these groups, group1, group2 and so on.

Each group has a dedicated job queue where data from the network is filtered and added to its corresponding group for processing.

At first I created a dedicated thread per group which would take data from the job queue, process it and then goes to blocking state (using Linked Blocking Queue).

But my senior suggested that i should use thread pools because this way threads wont get blocked and will be usable by other groups for processing.

But here is the thing, the data im getting is fast enough and the time a thread takes to process it is long enough for the thread to, possibly, not go into blocking mode. And this will also guarantee that data gets processed sequentially (job 1 gets done before job 2), which in pooling, very little chances are, might not happen.

My senior is also bent on the fact that pooling will also save us lots of memory because threads are POOLED (im thinking he really went for the word ;) ). While i dont agree to this because, i personally think, pooled or not each thread gets its own stack memory. Unless there is something in thread pools which i am not aware of.

One last thing, I always thought that pooling helps where jobs appear in a big number for short time. This makes sense because thread spawning would be a performance kill because of the time taken to init a thread is lot more than time spent on doing the job. So pooling helps a lot here.

But in my case group1, group2,...,groupN always remain alive. So if there is data or not they will still be there. So thread spawning is not the issue here.

My senior is not convinced and wants me to go with the pooling solution because its memory footprint is great.

So, which path to take?

Thank you.

评论

Good question. Pooling indeed saves you initialization time, as you said. But it has another aspect: resource management. And here I am asking you this- just how many groups (read- dedicated threads) do you have? do they grow dynamically during the execution span of the application?

For example, consider a situation where the answer to this question is yes. new Groups types are added dynamically. In this case, you might not want to dedicate a a thread to each one since there is technically no restrictions on the amount of groups that will be created, you will create a lot of threads and the system will be context switching instead of doing real work. Threadpooling to the rescue- thread pool allows you to specify a restriction on the maxumal number of threads that could be possibly created, with no regard to load. So the application may deny service from certain requests, but the ones that get through are handled properly, without critically depleting the system resources.

Considering the above, I is very possible that in your case, it is very much OK to have a dedicated thread for each group!

The same goes for your senior's conviction that it will save memory.. Indeed, a thread takes up memory on the heap, but is it really so much, if it is a predefined amount, say 5. Even 10- it is probably OK. Anyway, you should not use pooling unless you are a-priory and absolutely convinced that you actually have a problem!

Pooling is a design decision, not an architectural one. You can not-pool at the beggining and proceed with optimizations in case you find pooling to be beneficial after you encountered a performance issue.

Considering the serialization of requests (in order execution) it is no matter whether you are using a threadpool or a dedicated thread. The sequential execution is a property of the queue coupled with a single handler thread.

Creating a thread will consume resources, including the default stack per thread (IIR 512Kb, but configurable). So the advantage to pooling is that you incur a limited resource hit. Of course you need to size your pool according to the work that you have to perform.

For your particular problem, I think the key is to actually measure performance/thread usage etc. in each scenario. Unless your running into constraints I perhaps wouldn't worry either way, other than to make sure that you can swap one implementation for another without a major impact on your application. Remember that premature optimisation is the root of all evil. Note that:

"Premature optimization" is a phrase used to describe a situation where a programmer lets performance considerations affect the design of a piece of code. This can result in a design that is not as clean as it could have been or code that is incorrect, because the code is complicated by the optimization and the programmer is distracted by optimizing.

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • newFixedThreadPool与newSingleThreadExecutor的性能问题(Performance Issues with newFixedThreadPool vs newSingleThreadExecutor)
    问题 我正在尝试对我们的客户代码进行基准测试。 因此,我决定编写一个多线程程序来对我的客户端代码进行基准测试。 我正在尝试测量下面的方法需要多少time (95 Percentile) attributes = deClient.getDEAttributes(columnsList); 因此,下面是我编写的用于对上述方法进行基准测试的多线程代码。 在两种情况下,我看到了很多变化- 1)首先,使用20 threads并running for 15 minutes来处理多线程代码。 我得到95%的37ms 。 我正在使用- ExecutorService service = Executors.newFixedThreadPool(20); 2)但是,如果我使用以下命令在15 minutes运行同一程序, ExecutorService service = Executors.newSingleThreadExecutor(); 代替 ExecutorService service = Executors.newFixedThreadPool(20); 当我使用newFixedThreadPool(20)运行代码时,我得到95%的7ms百分位数,比上面的数字newFixedThreadPool(20) 。 谁能告诉我以下原因导致此类高性能问题的原因是什么?
  • 什么时候在C#中使用线程池? [关闭](When to use thread pool in C#? [closed])
    问题 关门了。 这个问题是基于意见的。 它当前不接受答案。 想要改善这个问题吗? 更新问题,以便可以通过编辑此帖子以事实和引用的形式回答。 2年前关闭。 改善这个问题 我一直在尝试学习C#中的多线程编程,对于何时使用线程池而不是创建自己的线程,我感到困惑。 一本书建议仅将线程池用于小型任务(无论什么意思),但我似乎找不到任何真正的指导方针。 在做出此编程决定时,需要考虑哪些注意事项? 回答1 如果您有许多需要不断处理的逻辑任务,并且希望并行执行,请使用pool + scheduler。 如果您需要同时执行与IO相关的任务(例如从远程服务器下载内容或访问磁盘),但需要每隔几分钟执行一次,那么请创建自己的线程并在完成后将其杀死。 编辑:关于一些注意事项,我将线程池用于数据库访问,物理/模拟,AI(游戏),以及用于在处理许多用户定义任务的虚拟机上运行的脚本任务。 通常,一个处理器池由每个处理器2个线程组成(现在大概是4个),但是,如果知道需要多少线程,则可以设置所需的线程数量。 编辑:制作自己的线程的原因是由于上下文的更改,(即当线程需要与它们的内存一起换入和换出该进程时)。 进行无用的上下文更改(例如,当您不使用线程时),就像他们可能说的那样,将它们闲置一圈,很容易会使程序性能降低一半(例如,您有3个睡眠线程和2个活动线程)。 因此,如果这些下载线程仅在等待
  • 处理程序与AsyncTask与线程[关闭](Handler vs AsyncTask vs Thread [closed])
    问题 关门了。 这个问题是基于意见的。 它当前不接受答案。 想要改善这个问题吗? 更新问题,以便可以通过编辑此帖子以事实和引用的形式回答。 1年前关闭。 改善这个问题 我对Android中的Handlers , AsyncTask和Threads之间的区别感到有些困惑。 我已经在StackOverflow上阅读了很多博客和问题。 Handler是后台线程,可为您提供与UI进行通信的功能。 例如,更新进度条应通过Handler完成。 使用处理程序,您可以利用MessagingQueues的优势,因此,如果您要计划消息或更新多个UI元素或执行重复任务。 AsyncTask类似,实际上,它们使用Handler ,但未在UI线程中运行,因此对于获取数据(例如,获取Web服务)非常有用。 稍后,您可以与UI进行交互。 但是, Thread无法与UI交互,提供更多的“基本”线程,您会错过AsyncTask所有抽象。 但是,我想在服务中运行套接字连接。 应该在处理程序或线程中运行,还是在AsyncTask ? 完全不需要UI交互。 我使用的性能是否有所不同? 同时,文档已得到重大改进。 回答1 正如使用Handlers进行Android后台处理的教程中一样,Vogella网站上的AsyncTask和Loaders指出: Handler类可用于注册到线程,并提供一个简单的通道将数据发送到该线程。
  • 线程池与线程生成(Thread Pool vs Thread Spawning)
    问题 有人可以列出线程生成与线程池之间的一些比较点,哪个比较好? 请考虑将.NET框架作为支持两者的参考实现。 回答1 线程池线程比常规线程便宜得多,它们可以池化线程所需的系统资源。 但是它们有很多限制,可能会使它们不适合使用: 您不能中止线程池线程没有简单的方法来检测线程池是否已完成,没有Thread.Join() 没有简单的方法可以封送线程池线程中的异常除了消息框,您无法在线程池线程上显示任何类型的UI 线程池线程的运行时间不应超过几秒钟线程池线程不应长时间阻塞 后两个约束是线程池调度程序的副作用,它试图将活动线程数限制为CPU可用的内核数。 如果您安排许多经常运行的长时间运行的线程,则可能导致长时间的延迟。 许多其他线程池实现都有类似的约束,即给予或接受。 回答2 “池”包含准备使用的可用“线程”列表,而“生成”指的是实际创建新线程。 “线程池”的有用之处在于“使用时间更短”:避免了创建时间的开销。 关于“哪个更好”:取决于。 如果创建时的开销有问题,请使用线程池。 在需要执行许多“短期任务”的环境中,这是一个常见问题。 正如其他人指出的那样,线程池存在“管理开销”:如果正确实现,则这是最小的。 例如,限制池中的线程数是微不足道的。 回答3 对于“更好”的某种定义,通常需要使用线程池。 在不知道用例是什么的情况下,请考虑使用线程池,您有固定数量的线程
  • Java长时间运行的任务线程中断与取消标志(Java long running task Thread interrupt vs cancel flag)
    问题 我的任务很长,例如: public void myCancellableTask() { while ( someCondition ) { checkIfCancelRequested(); doSomeWork(); } } 可以取消任务(请求取消,并且checkIfCancelRequested()检查取消标志)。 通常,当我编写这样的可取消循环时,我使用一个标志来指示已请求取消。 但是,我知道我也可以使用Thread.interrupt并检查线程是否已被中断。 我不确定哪种方法更合适,为什么呢? 谢谢, 杰夫 回答1 中断将从指定的等待条件列表中删除线程。 您自己的取消标志不会。 如果要中断对IO和事件的等待,请使用中断。 否则请使用您自己的。 回答2 使用中断的一个问题是,如果您不控制所有正在执行的代码,则由于其他人对如何在其库中处理中断的理解不清,因此冒着中断中断“适当地”工作的风险。 也就是说,API会围绕其对您所依赖的interrupt的处理而无形地导出一个API。 在您的示例中,假设doSomeWork位于第三方JAR中,如下所示: public void doSomeWork() { try { api.callAndWaitAnswer() ; } catch (InterruptedException e) { throw new
  • 核心池大小与ThreadPoolExecutor中的最大池大小(Core pool size vs maximum pool size in ThreadPoolExecutor)
    问题 当我们就ThreadPoolExecutor讨论时,核心池大小和最大池大小之间到底有什么区别? 可以借助示例进行解释吗? 回答1 从此博客文章中: 举这个例子。 起始线程池大小为1,核心池大小为5,最大池大小为10,队列为100。 随着请求的到来,将最多创建5个线程,然后将任务添加到队列中,直到达到100个。当队列已满时,将创建最大为maxPoolSize新线程。 一旦所有线程都被使用并且队列已满,任务将被拒绝。 随着队列的减少,活动线程的数量也会减少。 回答2 如果正在运行的线程> corePoolSize&<maxPoolSize ,则如果Total任务队列已满并且有新线程到达,则创建一个新Thread。 表单文档:(如果正在运行的线程数大于corePoolSize但小于maximumPoolSize ,则仅在队列已满时才创建新线程。) 现在,举一个简单的例子, ThreadPoolExecutor executorPool = new ThreadPoolExecutor(5, 10, 3, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(50)); 在这里,5是corePoolSize-意味着Jvm将为前5个任务为新任务创建新线程。 其他任务将被添加到队列中,直到队列已满(50个任务)。
  • Java的Fork / Join与ExecutorService-什么时候使用?(Java's Fork/Join vs ExecutorService - when to use which?)
    问题 我刚读完这篇文章:与Java-7 ForkJoinPool相比,Java-5 ThreadPoolExecutor有什么优势? 并认为答案不够直接。 您能用简单的语言和示例来说明Java 7的Fork-Join框架与较旧的解决方案之间的权衡吗? 我还阅读了Google在主题Java技巧上的第一名:何时使用javaworld.com上的ForkJoinPool与ExecutorService,但是本文没有回答when的标题问题,它主要讨论的是api的区别... 回答1 Fork-join允许您轻松执行分割和征服作业,如果要在ExecutorService执行,则必须手动ExecutorService 。 在实践中, ExecutorService通常用于同时处理许多独立请求(又称为事务),并且当您要加速一项连贯的工作时会使用fork-join。 回答2 Fork-join对于递归问题特别有用,在递归问题中,任务涉及运行子任务,然后处理其结果。 (这通常称为“分而治之...”,但这并没有揭示其基本特征。) 如果您尝试使用常规线程(例如,通过ExecutorService)来解决此类递归问题,那么最终将束缚线程,等待其他线程向它们传递结果。 另一方面,如果问题不具有这些特征,则使用fork-join并不会带来真正的好处。 参考: Java教程:Fork / Join。 Java技巧
  • 使用Rxjava Schedulers.newThread()与Schedulers.io()进行改造(Retrofit with Rxjava Schedulers.newThread() vs Schedulers.io())
    问题 在Retrofit网络请求中使用Schedulers.newThread()与Schedulers.io()什么好处。 我已经看到了许多使用io()示例,但是我想理解为什么。 情况示例: observable.onErrorResumeNext(refreshTokenAndRetry(observable)) .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread())... 与 observable.onErrorResumeNext(refreshTokenAndRetry(observable)) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread())... 我见过的原因之一是- newThread()为每个工作单元创建一个新线程。 io()将使用线程池 但是,这种争论对应用程序有什么影响? 还有其他哪些方面? 回答1 您正确使用Schedulers.io()的好处在于它使用了线程池,而Schedulers.newThread()没有使用线程池。 您应该考虑使用线程池的主要原因是它们维护了许多预先创建的线程,这些线程处于空闲状态并正在等待工作。 这意味着当您有工作要做时
  • 国内酒店稳定性治理实践之内部资源治理
    背景之前介绍了国内酒店稳定性治理实践之系统间依赖治理,我们对系统间的依赖进行了专项治理,涉及通用的限流、缓存、Dubbo、Http、DB、MQ 等。但是光治理系统间的依赖是不够的,我们还对系统内部资源进行了分析和治理。本篇文章重点讲述对系统内部资源的治理,主要包含使用降级、熔断、隔离、同步转异步等手段控制流程(限流在上篇已经介绍,本篇就不重复了),以及对线程池等核心资源进行治理。治理手段及方案降级、熔断这个主要应对的是外部接口或资源出现问题的场景。提前考虑一些处理方案,保证主流程不会因为异常情况中断。比较典型的是 P1 应用接口调用的 P3 应用接口,要保证 P3 接口出任何问题都不会影响 P1 应用接口的核心流程处理。1)核心接口内部涉及的外部调用做好降级调研及处理,优先无损降级,核心调用准备好有损降级的手段。2)非核心场景查询外部接口做熔断处理(主要根据失败率和响应时间),这里要注意熔断后的处理,提前定义好返回的默认值或者定义的异常。3)关于熔断,推荐提前准备熔断后的替代接口、替代资源或默认值返回,并且能动态调节熔断阈值。4)规范(不强制):新需求及重构支持降级回修改之前,新增功能支持下线,这样能大幅度降低发布的风险。隔离这个主要应对的是相同资源中部分资源出问题影响其他资源的场景。1)线程池隔离:这个出问题影响很大,主要涉及 dubbo 线程池、自定义的业务线程池、jdk8
  • Thread.sleep()VS Executor.scheduleWithFixedDelay()(Thread.sleep() VS Executor.scheduleWithFixedDelay())
    问题 目标:偶尔执行某些代码。 问题:就性能而言,以下各项之间是否存在显着差异: while(true) { execute(); Thread.sleep(10 * 1000); } 和 executor.scheduleWithFixedDelay(runnableWithoutSleep, 0, 10, TimeUnit.SECONDS); ? 当然,后一种选择更适合犹太人。 但是,我想知道是否应该进行一次冒险,即“花几天时间重构遗留代码以告别Thread.sleep()”。 更新:此代码在超级/大型/超级高负载环境中运行。 回答1 您正在处理以数十秒为单位的睡眠时间。 通过在此处更改睡眠选项可能节省的时间可能是几微秒或几微秒。 我每次都希望使用后一种样式,但是如果您拥有前一种样式,并且要对其进行更改会花费很多成本,那么“提高性能”并不是一个特别好的理由。 编辑re:8000个线程 8000个线程真是太糟糕了; 我可能会移到计划的执行程序,以便您可以控制系统上的负载量。 关于变化的唤醒时间的观点值得我们注意,尽管我认为更大的风险是所有睡眠的线程的冲动,然后连续唤醒并争夺所有系统资源。 我会花时间将所有这些都扔到固定的线程池预定执行器中。 并发运行的资源与有限资源(例如,#个核心或#个IO路径)的可用资源一样多,另外还有几个可以并行运行。 这将为您提供良好的吞吐量,但会增加延迟
  • FixedThreadPool与CachedThreadPool:两种弊端中的较小者(FixedThreadPool vs CachedThreadPool: the lesser of two evils)
    问题 我有一个程序产生线程(〜5-150)来执行一堆任务。 最初,我使用了FixedThreadPool因为这个类似的问题表明它们更适合寿命更长的任务,并且由于我对多线程的了解非常有限,我认为线程的平均寿命(几分钟)是“寿命长”。 但是,我最近添加了产生更多线程的功能,并且这样做使我超出了所设置的线程限制。 在这种情况下,最好猜测并增加我可以允许的线程数,或者切换到CachedThreadPool以免浪费线程? 初步尝试将它们都尝试一下,似乎没有什么区别,所以我倾向于使用CachedThreadPool以避免浪费。 但是,线程的寿命是否意味着我应该改为选择一个FixedThreadPool并仅处理未使用的线程? 这个问题使这些多余的线程似乎没有浪费,但我希望您能澄清一下。 回答1 CachedThreadPool正是您应根据情况使用的,因为对于长时间运行的线程使用CachedThreadPool不会产生负面影响。 Java文档中有关CachedThreadPools适用于短期任务的评论仅表明它们特别适合此类情况,而不是不能或不应该将它们用于涉及长期运行任务的任务。 为了进一步详细说明,Executors.newCachedThreadPool和Executors.newFixedThreadPool都由相同的线程池实现(至少在开放式JDK中)支持,只是具有不同的参数。
  • 线程和进程与多线程和多核/多处理器:如何映射?(Threads & Processes Vs MultiThreading & Multi-Core/MultiProcessor : How they are mapped?)
    问题 我很困惑,但是以下线索消除了我的疑虑: 多处理,多线程,超线程,多核 但是它从硬件的角度解决了查询。 我想知道这些硬件功能如何映射到软件? 显而易见的是,MultiProcessor(= Mutlicpu)和MultiCore之间没有区别,除了在多核中,所有的cpus都驻留在一个芯片(管芯)上,就像在多处理器中,所有的cpus都在自己的芯片上并连接在一起。 因此,mutlicore /多处理器系统能够在“同一时间”执行多个进程(firefox,mediaplayer,googletalk)(与上下文在单个处理器系统上切换这些进程不同)是吗? 如果正确的话。 到目前为止,我还很清楚。 但是,当多线程出现时,就会引起混乱。 多线程“用于”并行处理。 正确的? cpu中的多线程涉及哪些元素? 图表? 对于我来说,要利用两个独立任务的并行处理功能,CPU的需求应该是什么? 当人们说线程的上下文切换时。 我真的不明白。 因为如果它的上下文切换线程,那么它就不能并行处理。 线程必须“同时严格执行”。 正确的? 我的多线程概念是:考虑具有单个cpu的系统。 当进程上下文切换为Firefox时。 (假设)firefox的每个选项卡都是一个线程,并且所有线程都严格同时执行。 不像一个线程执行了一段时间,然后另一个线程又占用了一个,直到上下文切换时间到了。
  • TNonblockingServer,TThreadedServer和TThreadPoolServer,哪一种最适合我的情况?(TNonblockingServer, TThreadedServer and TThreadPoolServer, which one fits best for my case?)
    问题 我们的分析服务器是用C ++编写的。 它基本上查询底层存储引擎,并通过节俭返回相当大的结构化数据。 一个典型的请求大约需要0.05到0.6秒才能完成,具体取决于请求的大小。 我注意到,对于可以在c ++代码中使用的Thrift服务器,有一些选择,特别是TNonblockingServer,TThreadedServer和TThreadPoolServer。 似乎TNonblockingServer是可行之路,因为它可以支持更多并发请求,并且仍在后台使用线程池来处理任务。 它还避免了构建/销毁线程的成本。 Facebook的节俭更新:http://www.facebook.com/note.php?note_id=16787213919 在Facebook,我们正在为C ++开发一个完全异步的客户端和服务器。 该服务器使用像当前TNonblockingServer一样的事件驱动的I / O,但是它与应用程序代码的接口全部基于异步回调。 这将使我们能够编写仅需几个线程即可处理数千个同时请求(每个请求都需要调用其他Thrift或Memcache服务器)的服务器。 有关stackover的相关文章:节俭中有大量同时连接 话虽如此,您不一定能够真正地更快地工作(处理程序仍在线程池中执行),但是更多的客户端将能够立即连接到您。 只是想知道我还有其他因素吗? 如何确定最适合我的需求?
  • inter_op_parallelism_threads和intra_op_parallelism_threads的含义(Meaning of inter_op_parallelism_threads and intra_op_parallelism_threads)
    问题 有人可以解释以下TensorFlow术语吗 inter_op_parallelism_threads intra_op_parallelism_threads 或者,请提供指向正确说明源的链接。 我通过更改参数进行了一些测试,但结果并不一致,无法得出结论。 回答1 tf.ConfigProto协议缓冲区的源中记录了inter_op_parallelism_threads和intra_op_parallelism_threads选项。 这些选项配置了TensorFlow用来并行化执行的两个线程池,如注释所述: // The execution of an individual op (for some op types) can be // parallelized on a pool of intra_op_parallelism_threads. // 0 means the system picks an appropriate number. int32 intra_op_parallelism_threads = 2; // Nodes that perform blocking operations are enqueued on a pool of // inter_op_parallelism_threads available in each process
  • Java线程和内核数(Java threads and number of cores)
    问题 我只是对处理器和线程如何工作提出了一个简短的问题。 根据我目前的理解,一个内核一次只能执行1个进程。 但是我们能够产生一个线程池(比方说30个),该线程池的个数大于我们所拥有的(等于4个)内核的数量,并使它们并发运行。 如果我们只有4个核心,这怎么可能? 我还可以在本地计算机上运行30线程程序,还可以继续在计算机上执行其他活动,例如看电影或浏览Internet。 我读过某处发生了线程调度,并且给人一种错觉,即这30个线程由4个内核同时运行。 这是真的吗?如果可以的话,有人可以解释一下它是如何工作的,并建议对此进行一些阅读吗? 预先感谢您的帮助。 回答1 进程与线程 在过去,每个进程仅具有一个执行线程,因此将进程直接调度到内核上(而在过去,几乎只有一个内核可以调度到该内核上)。 但是,在支持线程的操作系统(几乎是所有现代操作系统)中,线程是线程,而不是预定的进程。 因此,在本讨论的其余部分中,我们将只讨论线程,并且您应该了解每个正在运行的进程都有一个或多个执行线程。 并行与并发 当两个线程并行运行,它们都在同一时间运行。 例如,如果我们有两个线程A和B,则它们的并行执行将如下所示: CPU 1:A -------------------------> CPU 2:B -------------------------> 当两个线程同时运行,它们的执行重叠。
  • GreenletVS。 线程数(Greenlet Vs. Threads)
    问题 我是gevents和greenlets的新手。 我找到了一些有关如何使用它们的很好的文档,但是没有一个文档为我提供有关如何以及何时使用greenlets的理由! 他们真正擅长的是什么? 是否在代理服务器中使用它们是一个好主意吗? 为什么不线程? 我不确定的是,如果它们基本上是例程,它们如何为我们提供并发性。 回答1 Greenlets提供并发性,但不提供并行性。 并发是指代码可以独立于其他代码运行的时候。 并行是同时执行并发代码。 当在用户空间中有很多工作要做时,并行性特别有用,而这通常是占用大量CPU的工作。 并发对于解决问题非常有用,它可以更轻松地并行调度和管理不同的部分。 Greenlets确实在网络编程中大放异彩,其中与一个套接字的交互可以独立于与其他套接字的交互而发生。 这是并发的经典示例。 由于每个greenlet都在其自己的上下文中运行,因此您可以继续使用同步API,而无需使用线程。 这样做很好,因为线程在虚拟内存和内核开销方面非常昂贵,因此线程可以实现的并发性要少得多。 此外,由于使用GIL,Python中的线程比平时更昂贵且更受限制。 并发的替代方法通常是Twisted,libevent,libuv,node.js等项目,其中所有代码共享相同的执行上下文,并注册事件处理程序。 使用greenlet(具有适当的网络支持,例如通过gevent
  • 什么时候不应该在.Net中使用ThreadPool? [关闭](When should I not use the ThreadPool in .Net? [closed])
    问题 关门了。 这个问题需要更加集中。 它当前不接受答案。 想要改善这个问题吗? 更新问题,使其仅通过编辑此帖子即可将重点放在一个问题上。 5年前关闭。 改善这个问题 我什么时候不应该使用.NET中的线程池? 看起来最好的选择是使用ThreadPool,在这种情况下,为什么它不是唯一的选择? 您对此有何经验? 回答1 我不将ThreadPool用于廉价的多线程的唯一原因是,如果我需要... 与正在运行的方法进行交互(例如,杀死它) 在STA线程上运行代码(这发生在我身上) 在我的应用程序ThreadPool后使线程保持活动状态( ThreadPool线程是后台线程) 万一我需要更改线程的优先级。 我们无法在ThreadPool中更改线程的优先级,默认情况下为Normal。 PS: MSDN文章“托管线程池”包含一个标题为“何时不使用线程池线程”的部分,其中有一个非常相似但更完整的不使用线程池的可能原因列表。 有很多原因导致您需要跳过ThreadPool ,但是如果您不了解它们,那么ThreadPool应该足够适合您。 或者,查看新的Parallel Extensions Framework,其中包含一些可以满足您需求的简洁东西,而无需使用ThreadPool 。 回答2 @Eric,我将不得不同意Dean的观点。 线程很昂贵。 您不能假设您的程序是唯一正在运行的程序。
  • Node.JS中的单线程事件循环与多线程非阻塞工作者(Single Threaded Event Loop vs Multi Threaded Non Blocking Worker in Node.JS)
    问题 Node.JS的最大优点是它具有非阻塞性。 它是单线程的,因此不需要为每个新的传入连接生成新的线程。 在事件循环(实际上是单线程)的后面,有一个“非阻塞工作程序”。 这个东西不再是单线程的,所以(据我了解),它可以为每个任务产生一个新线程。 也许我误会了一些东西,但是优势到底在哪里。 如果要处理的任务很多,那么“非阻塞工作”会不会变成“阻塞工作人员”? 谢谢克里斯蒂安 回答1 您需要阅读libuv,它是节点的非阻塞I / O背后的“魔术”。 从libuv书中摘录的重要一件事是libuv使用主机OS的异步I / O设施。 它不只是为每个连接创建一个新线程。 libuv告诉操作系统,它想知道在一组特定的套接字上发生的任何更改(连接状态,接收到的数据等)。 然后由操作系统来处理管理连接。 操作系统本身可能会创建一个或多个线程来完成此任务,但这不是我们关心的问题。 (它当然不会为每个连接创建一个线程。) 对于其他类型的操作,例如对C库的调用可能在计算上是昂贵的(即,加密),libuv提供了可以在其上运行这些操作的线程池。 由于它是一个线程池,因此您不必担心线程数无限制地增长。 当池完全繁忙时,操作将排队。 是的,JavaScript在单个线程上运行。 是的,节点(通过libuv)在后台产生了许多线程来工作,因此它不需要阻塞JavaScript线程。 但是,线程数始终受控制,并且I /
  • C#多线程(12):线程池
    目录线程池ThreadPool 常用属性和方法线程池说明和示例线程池线程数线程池线程数说明不支持的线程池异步委托任务取消功能计时器线程池线程池全称为托管线程池,线程池受 .NET 通用语言运行时(CLR)管理,线程的生命周期由 CLR 处理,因此我们可以专注于实现任务,而不需要理会线程管理。线程池的应用场景:任务并行库 (TPL)操作、异步 I/O 完成、计时器回调、注册的等待操作、使用委托的异步方法调用和套接字连接。很多人不清楚 Task、TaskThreadPool 常用属性和方法属性:属性说明CompletedWorkItemCount获取迄今为止已处理的工作项数。PendingWorkItemCount获取当前已加入处理队列的工作项数。ThreadCount获取当前存在的线程池线程数。方法:方法说明BindHandle(IntPtr)将操作系统句柄绑定到 ThreadPool。BindHandle(SafeHandle)将操作系统句柄绑定到 ThreadPool。GetAvailableThreads(Int32, Int32)检索由 GetMaxThreads(Int32, Int32) 方法返回的最大线程池线程数和当前活动线程数之间的差值。GetMaxThreads(Int32, Int32)检索可以同时处于活动状态的线程池请求的数目。
  • C#学习日记6
    1.索引器 解析: [1]索引也是一种类成员,而且必须为实例成员,因为它就是为实例成员提供的一种访问方式,所以不能声明为static [2]索引与属性类似,也有get访问器和set访问器,而且索引实际上就是一组get访问器和set访问器 [3]索引器经常是在主要用于封装内部集合或数组的类型中声明的 2.索引器和属性的比较 解析: [1]相同点 ①索引和属性都不用分配内存位置来存储。 ②索引和属性都是为类的其它成员提供访问控制的。 ③索引和属性都有get访问器和set访问器,它们可以同时声明两个访问器,也可以只声明其中一个。 [2]不同点 ①属性通常表示单独的数据成员,而索引表示多个数据成员。 ②属性既可以声明为实例属性,也可以声明为静态属性,而索引不能声明为静态的。 ③属性有简洁的自动实现属性,而索引必须声明完整。 ④get访问器:属性的get访问器没有参数,索引器的get访问器具有与索引器相同的形参表。 ⑤set访问器:属性的set访问器包含隐式value参数。除了值参数外,索引器的set访问器还具有与索引器相同的形参表。 3.Thread.Sleep(0) 解析:这样调用会导致线程立即放弃本身当前的时间片,自动将CPU移交给其它线程。 4.Thread.yield() 解析: [1]主动放弃当前线程的时间片,并让操作系统调度其它就绪态的线程使用一个时间片 [2