如何避免等待线程完成执行 - Python

时间:2015-12-29 11:51:24

标签: python multithreading

我在Python中定义了以下结构 -

enter image description here

有两个主题。每个线程垂直向下扫描分支并打印其值。到达该分支的末端时,它沿水平轴向前移动一步。就像,Thread1将打印a1,a2和a3。同时,线程2将扫描b1。当线程完成执行时,线程1将跳转到块B,线程2将跳转到块C以执行相同的过程。

完成所有块后,该过程从头开始。我写了一个相同的脚本 -

def printTags(DevObj):
    if DevObj == None:
        return -1
    TagObj = DevObj.tagPointer
    while TagObj != None:
        time.sleep(5)
        print TagObj.id
        TagObj = TagObj.nextTag

import threading, thread

# temp1 points to Block A.
# temp2 points to Block B.

while True:
    t1 = threading.Thread(target=printTags, args=(temp1,))
    t2 = threading.Thread(target=printTags, args=(temp2,))
    t1.start()
    t2.start()
    t1.join()
    t2.join()

    if temp1.nextDevice != None:
        temp1 = temp1.nextDevice
    else:
        temp1 = start.nextDevice

    if temp2.nextDevice != None:
        temp2 = temp2.nextDevice
    else:
        temp2 = start.nextDevice 

但是,您可以看到,当线程在块A和B上工作时,线程1将比线程2花费更多时间,因为它必须打印更多值。因此,线程2在一段时间内仍未使用。我想避免这个空闲时间。我怎么能这样做?

1 个答案:

答案 0 :(得分:1)

您可以采取不同的方法,但我想指出其中两种方法:

首先,使用Semaphore,这个和你的代码一样接近,但实际上并不可取:

from threading import Semaphore

def printTags(DevObj, s):
    ...
    s.release()
    ...

import threading, thread

# temp1 points to Block A.
# temp2 points to Block B.


s = Semaphore(0)
threads = [
    threading.Thread(target=printTags, args=(THING_TO_DO,s))
    for THING_TO_DO in THINGS_TO_DO
]
for t in threads:
    t.start()

while True:
    s.aquire()
    for t in threads:
        # give more work

更优选的选项是使用生产者/消费者模式:

from threading import Semaphore

STOP = object()

def printTags(queue):
    while True:
        thing_to_process = queue.get()
        if thing_to_process is STOP:
            return
        else:
            #process 

import threading, thread

# temp1 points to Block A.
# temp2 points to Block B.

THREAD_COUNT = 2
s = Semaphore(0)
threads = [
    threading.Thread(target=printTags, args=(queue,))
    for _ in xrange(THREAD_COUNT)
]

for thing in things:
    queue.put(thing)
for _ in xrange(THREAD_COUNT):
    queue.put(STOP)

for t in threads:
    t.start()