Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python threading design

I'm trying to write a mini-game that allows me to practice my python threading skill. The game itself involves with timed bombs and citys that have them.

Here is my code:

class City(threading.Thread):

    def __init__(self, name):
        super().__init__()
        self.name = name
        self.bombs = None
        self.activeBomb = None
        self.bombID = 0
        self.exploded = False

    def addBomb(self, name, time, puzzle, answer, hidden=False):
        self.bombs.append(Bomb(name, self.bombID, time, puzzle, answer, hidden))
        self.activeBomb.append(self.bombID)
        self.bombID += 1

    def run(self):
        for b in self.bombs:
            b.start()
        while True:
            # listen to the bombs in the self.bombs # The part that I dont know how

            # if one explodes
            #   print(self.name + ' has been destroyed')
            #   break
            # if one is disarmed
            #   remove the bombID from the activeBomb
            # if all bombs are disarmed (no activeBomb left)
            #       print('The city of ' + self.name + ' has been cleansed')
            #   break


class Bomb(threading.Thread):

    def __init__(self, name, bombID, time, puzzle, answer, hidden=False):
        super(Bomb, self).__init__()
        self.name = name
        self.bombID = bombID
        self._timer = time
        self._MAXTIME = time
        self._disarmed = False
        self._puzzle = puzzle
        self._answer = answer
        self._denoted = False
        self._hidden = hidden

    def run(self):
        # A bomb goes off!!
        if not self._hidden:
            print('You have ' + str(self._MAXTIME)
                  + ' seconds to solve the puzzle!')
            print(self._puzzle)
        while True:
            if self._denoted:
                print('BOOM')
                // Communicate to city that bomb is denoted
                break
            elif not self._disarmed:
                if self._timer == 0:
                    self._denoted = True
                else:
                    self._timer -= 1
                    sleep(1)
            else:
                print('You have successfully disarmed bomb ' + str(self.name))
                // Communicate to city that this bomb is disarmed
                break

    def answerPuzzle(self, ans):
        print('Is answer ' + str(ans) + ' ?')
        if ans == self._answer:
            self._disarmed = True
        else:
            self._denotaed = True

    def __eq__(self, bomb):
        return self.bombID == bomb.bombID

    def __hash__(self):
        return id(self)

I currently don't know what is a good way for the City class to effectively keep track of the bomb status.

The first thought I had was to use a for loop to have the City to check all the bombs in the City, but I found it being too stupid and inefficient

So here is the question:

What is the most efficient way of implementing the bomb and City so that the city immediately know the state change of a bomb without having to check it every second?

PS: I do NOT mean to use this program to set off real bomb, so relax :D

like image 969
user1948847 Avatar asked Apr 02 '26 21:04

user1948847


1 Answers

A good case to use queue. Here is an example of the so-called producer - consumer pattern.

The work threads will run forever till your main program is done (that is what the daemon part and the "while True" is for). They will diligently monitor the in_queue for work packages. They will process the package until none is left. So when the in_queue is joined, your work threads' jobs are done. The out_queue here is an optional downstream processing step. So you can assemble the pieces from the work threads to a summary form. Useful when they are in a function.

If you need some outputs, like each work thread will print the results out to the screen or write to one single file, don't forget to use semaphore! Otherwise, your output will stumble onto each other.

Good luck!

from threading import Thread
import Queue

in_queue = Queue.Queue()
out_queue = Queue.Queue()

def work():
    while True:
        try:
            sonId = in_queue.get()
        ###do your things here
            result = sonID + 1

        ###you can even put your thread results again in another queue here
            out_queue.put(result)   ###optional


        except:
            pass
        finally:
            in_queue.task_done()

for i in range(20):

    t = Thread(target=work)
    t.daemon = True
    t.start()


for son in range(10):    
    in_queue.put(son)


in_queue.join()

while not out_queue.empty():

    result = out_queue.get()

    ###do something with your result here

    out_queue.task_done()

out_queue.join()
like image 91
dgg32 Avatar answered Apr 04 '26 10:04

dgg32



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!