简体   繁体   中英

Simple threads example in Python

I have question about threading in Python (I admit, I'm newbie on this subject).

I have object and I want to generate list of numbers in method part1() (with some random time interval) and with part2() - print ASAP all generated numbers.

Here is my code:

import random
import time
from threading import Thread


class GenerateRand:
    def __init__(self):
        self.h = []

    def part1(self):
        while True:
            r = random.choice(range(9))
            self.h.append(r)
            print "Rand in list:", self.h
            time.sleep(random.randint(1, 100)/100.0)

    def part2(self):
        while True:
            if self.h:
                print "Get:", self.h.pop()


if __name__ == "__main__":
    obj = GenerateRand()
    th1 = Thread(target = obj.part1)
    th2 = Thread(target = obj.part2)
    th1.start()
    th2.start()
    th1.join()
    th2.join()

This works fine, but prints from threads are mixed. Is this code OK? Is there a better ("pythonic" :) way to do this?

This is a classic producer-consumer problem. It is better to use a Queue for message passing between the threads (the messages in your case are the random numbers in r ), to avoid the busy-wait, which consumes unnecessary cpu time. Queue.get() allows waiting for the next message un-busy-ly.

Other than that, your solution is just fine. That's exactly how you'd go about implementing such flow. I personally prefer subclassing threading.Thread rather than using the target argument, but for the simple cases, using target is fine. ( more details here ).

And of course it is ok that the printed output is "mixed". The print commands output to the same place (stdout), and the order in which they are executed is not guaranteed. After all, they are different threads...

If you want to avoid your text output getting scrambled, you can add a lock to the class

class GenerateRand:
    def __init__(self):
        self.h = []
        self.lock = threading.Lock()

    def part1(self):
        while True:
            r = random.choice(range(9))
            self.lock.acquire()
            self.h.append(r)
            print("added: " + str(self.h))
            self.lock.release()
            time.sleep(random.randint(1,100)/100.0)
    def part2(self):
        while True:
            if self.h:
                self.lock.acquire()
                print( "popped: " + str( self.h.pop()))
                self.lock.release()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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