I have the following structure defined in Python -
There are two threads. Each thread scans the branch vertically downwards and prints its value. On reaching the end of that branch, it moves a step ahead along the horizontal axis. Like, Thread1 will print a1, a2 and a3. At the same time, Thread 2 will scan b1. When both the thread finish execution, Thread 1 will jump to block B and Thread 2 will jump to block C to carry out the same process.
When all the blocks are done, the process starts again from the beginning. I have written a script for the same -
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
However, you can see that when the threads are working on block A and B, Thread 1 will take more time than Thread 2 as it has to print more values. Because of this, Thread 2 remains unused for some time. I want to avoid this idle time. How can I do so?
解决方案
There are different approaches you can take, but I would like to point out two of them:
First, use Semaphore, this one as close as your code but it is not preferable really:
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
More preferred option is to use producer/consumer pattern:
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()