简体   繁体   English

制作工人线程?

[英]Making worker threads?

Is there a way to make "worker threads" Basically I tried creating threads every time I needed them and this resulted in being slower than with 1 thread becase creating a new thread all the time is expensive. 有没有办法制作“工作线程”基本上我每次需要时都尝试创建线程,这导致比1线程慢,因为创建新线程总是很昂贵。 Would there be a way to create worker threads when the application first starts, then give them work when necessary? 是否有办法在应用程序首次启动时创建工作线程,然后在必要时让它们工作?

Thanks 谢谢

Yes, you can create the threads up front and have them wait for signals to go and start their work. 是的,您可以预先创建线程并让它们等待信号开始工作。

These signals can be message queues or semaphores or any other sort of inter-thread communication method. 这些信号可以是消息队列或信号量或任何其他类型的线程间通信方法。

As an example, we once put together a system under UNIX which had a master thread to receive work over the net and farm the jobs out to slave threads. 作为一个例子,我们曾经在UNIX下组建了一个系统,该系统有一个主线程,可以通过网络接收工作并将作业转移到从属线程。 The slave threads would actually have to interact with another system by screen scraping (basically emulating a user) to get their desired information. 从属线程实际上必须通过屏幕抓取(基本上模拟用户)与另一个系统交互以获得他们想要的信息。

In other words, work could come in faster than slave threads could do it. 换句话说,工作可以比奴隶线程更快地完成。

So we started up about fifty odd slaves and just created a condition variable for them (this was using pthreads). 所以我们启动了大约五十个奇怪的奴隶,并为他们创建了一个条件变量(这是使用pthreads)。 Each slave that wasn't doing active work simply waited on the condition variable. 每个没有进行活动工作的从站只是等待条件变量。

When a job came in to the master thread, it loaded the relevant data into known memory and "kicked" the condition variable, waking up one of the slaves which would then grab the work and start processing it (after notifying the master that it could continue). 当一个作业进入主线程时,它将相关数据加载到已知存储器中并“踢”条件变量,唤醒其中一个从器件然后抓取工作并开始处理它(在通知主器件之后它可以继续)。

So there was no overhead in having to create threads on the fly - all were created on application start-up and simply waited for work to be handed over. 因此,在运行中创建线程没有任何开销 - 所有这些都是在应用程序启动时创建的,只是等待工作交付。

Of course, there's a potential downside to this sort of static sizing in that you may get into trouble if you actually need more threads. 当然,这种静态大小的潜在缺点是,如果你真的需要更多的线程,你可能会遇到麻烦。 We solved it by simply monitoring the maximum number of threads and ensuring the process was restarted the following day with more if we were consistently running out. 我们通过简单地监视最大线程数来确保解决它,并确保在第二天重新启动进程,如果我们一直在用完则更多。


If you want to have a more dynamic solution, you need to look into a concept called thread pooling. 如果您想要一个更动态的解决方案,您需要研究一个称为线程池的概念。 This is basically what I've described above but it generally lets you set a minimum and maximum number of threads along with a maximum time an inactive thread will be allowed to survive without work (unless you're already at the minimum). 这基本上就是我上面所描述的,但它通常允许您设置最小和最大线程数以及非活动线程在没有工作的情况下生存的最长时间(除非您已经处于最低限度)。

Its implementation could be something as simple as: 它的实现可能很简单:

master:
    minslaves = 7
    maxslaves = 20
    maxtime = 600
    numslaves = 0
    freeslaves = 0

    while running:
        while numslaves < minslaves:
            increment numslaves and freeslaves
            start a slave
        endwhile
        wait for work
        if freeslaves = 0 and numslaves < maxslaves:
            start a slave
        endif
        queue work to slavequeue
    endwhile
    while numslaves > 0:
        wait
    endwhile
    exit

and: 和:

slave:
    while running:
        get work from slavequeue with timeout
        if timed out:
            if time since last work > maxtime and numslaves > minslaves:
                break out of while loop
            endif
            restart while loop
        endif
        decrement freeslaves
        do the work
        increment freeslaves
    endwhile
    decrement numslaves and freeslaves
    exit

(with proper semaphore protection of all shared variables of course, numslaves , freeslaves , slavequeue and the others if you decide to change them after threads have been started). (当然,如果您决定在线程启动后更改它们, freeslaves当然,所有共享变量都有适当的信号量保护, numslavesfreeslavesslavequeue和其他变量)。

And, if your environment already has thread pooling, I suggest you use it rather than trying to convert my pseudo-code above. 并且,如果您的环境已经有线程池,我建议您使用它而不是尝试转换上面的伪代码。 My code is from memory and is meant to illustrate a point - it may or may not be bug-free :-) 我的代码来自内存,旨在说明一点 - 它可能是也可能不是无bug :-)

This is usually done by creating message queues. 这通常通过创建消息队列来完成。 A thread would wait on some object, signaling of which will indicate there's new work to complete. 一个线程会在某个对象上等待,其中的信号将指示需要完成的新工作。

On win32 there is a very good threadpool - esp vista and windows 7 onwards. 在win32上有一个非常好的线程池 - esp vista和windows 7以上。 I've always found it useful to think in terms of tasks that need to be performed concurrently than thinking of individual threads. 我总是发现,考虑需要同时执行的任务而不是考虑单个线程,这是有用的。

Also, the parallel patterns library (ConcRT I think it is called) that comes with Visual C++ 2010 looks very powerful (and has a simple interface). 此外,Visual C ++ 2010附带的并行模式库(我认为它被称为ConcRT)看起来非常强大(并且具有简单的接口)。 I haven't used it yet myself though. 我自己还没有用过它。 The MSDN link is - http://msdn.microsoft.com/en-us/library/dd492418.aspx MSDN链接是 - http://msdn.microsoft.com/en-us/library/dd492418.aspx

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM