Reputation: 445
I'm new to threading and queue. So, I wrote this program where I'm trying to return a value to one of the 2 functions in the threading class MyThread and print/process the returned value in the main() function :
import threading
import datetime
import Queue
a=Queue.Queue()
b=Queue.Queue()
q=Queue.Queue()
class MyThread(threading.Thread):
def __init__(self,q):
threading.Thread.__init__(self)
self.que=q
t1=threading.Thread(target=self.prints,args=(4,))
t2=threading.Thread(target=self.printy,args=(6,self.que,))
t1.start()
t2.start()
item=self.que.get()
print(item)
print "*"*30
it=item*2
print(it)
t1.join()
t2.join()
def main(self):
t3=threading.Thread(target=self.prints,args=(3,))
t4=threading.Thread(target=self.printy,args=(5,self.que,))
t3.start()
t4.start()
item=self.que.get()
print(item)
print "#"*30
it=item*2
print(it)
t3.join()
t4.join()
def prints(self,i):
while(i>0):
print "i="+str(i)+" "+str(datetime.datetime.now().time())+"\n"
i=i-1
def printy(self,i,b):
r=0
while(i<10):
print "i="+str(i)+" "+str(datetime.datetime.now().time())+"\n"
i=i+1
r=r+i
self.que.put(r)
if __name__=='__main__':
MyThread(a).main()
However, even though I manage to get the output as I want. I'm curious to know that how the same can be achieved if my function printy() is modified as below:
def printy(self,i,b):
r=0
while(i<10):
print "i="+str(i)+" "+str(datetime.datetime.now().time())+"\n"
i=i+1
r=r+i
return(r)
How could queue be used to get the returned values? Or do we have any alternate way to do this?
Upvotes: 0
Views: 1580
Reputation: 5323
You only ever put items in the queue but never get them out. At the end of __init__
, however, you join the queue, which blocks until the queue has been consumed. Since up until that point, no consumer has been launched, it will block forever.
I'm not sure what you're trying to achieve: now your program will terminate with the queue still active in the background; in both __init__
and main
, you put in 4 items but get out only one. If that really produces the output you want, I'm not sure what to suggest.
On the other hand, assuming that you're trying to implement a producer-consumer system, you could something like this:
import Queue
import threading
class ProduceConsume(object):
def produce(self, n):
for i in xrange(n):
print 'producing {}'.format(i)
self.queue.put(i)
def consume(self):
while self.running:
try:
i = self.queue.get(timeout=0.1)
except Queue.Empty:
continue
print 'consuming {}'.format(i)
self.queue.task_done()
def main(self, n):
self.queue = Queue.Queue()
self.running = True
consumer = threading.Thread(target=self.consume)
consumer.start()
producer = threading.Thread(target=self.produce, args=(n,))
producer.start()
producer.join()
self.queue.join()
self.running = False
consumer.join()
ProduceConsume().main(4)
Now, if you want to obtain a kind of result value from the producer thread (the one that puts items in the queue like your printy
, you cannot simply return it since the return value of a thread's execution target isn't used. You could store it somewhere (maybe as an attribute on your ProduceConsume
instance) and access it after the producer thread has been joined. Since you ask how to use the queue for it, however, you'd need to put it in the queue as the last item and handle it appropriately in the consumer thread:
def produce(self, n):
r = 0
for i in xrange(n):
print 'producing {}'.format(i)
self.queue.put(i)
r += i
self.queue.put(r)
def consume(self):
while self.running:
try:
i = self.queue.get(timeout=0.1)
except Queue.Empty:
continue
print 'consuming {}'.format(i)
self.queue.task_done()
else:
print 'result was: {}'.format(i)
To further avoid treating the result as just another item before finding that it was the last item gotten from the queue, you'll need more complex items, such as ('item', i)
and ('result', r)
that tell you whether they represent a regular item or the result.
Upvotes: 1