如何从两个不同的对象生成线程并在pythonv2.7中协调它们?

2024-10-03 11:25:06 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图把从两个不同的python问题中得到的答案结合起来。你知道吗

这是第一个问题和答案。基本上我只想产生两个线程,一个到powerDown()另一个到powerUp(),powerUp()在powerDown()上挂起

How to spawn a thread inside another thread in the same object in python?

import threading

class Server(threading.Thread):
    # some code
    def run(self):
        self.reboot()

    # This is the top level function called by other objects
    def reboot(self):
        # perhaps add a lock
        if not hasattr(self, "_down"):
            self._down = threading.Thread(target=self.__powerDown)
            self._down.start()
            up = threading.Thread(target=self.__powerUp)
            up.start()

    def __powerDown(self):
        # do something

    def __powerUp(self):
        if not hasattr(self, "_down"):
            return
        self._down.join()
        # do something
        del self._down

这是第二个问题和答案。基本上我想启动一个线程,然后调用对象的函数。你知道吗

How to call a function on a running Python thread

import queue
import threading

class SomeClass(threading.Thread):
    def __init__(self, q, loop_time = 1.0/60):
        self.q = q
        self.timeout = loop_time
        super(SomeClass, self).__init__()

    def onThread(self, function, *args, **kwargs):
        self.q.put((function, args, kwargs))

    def run(self):
        while True:
            try:
                function, args, kwargs = self.q.get(timeout=self.timeout)
                function(*args, **kwargs)
            except queue.Empty:
                self.idle()

    def idle(self):
        # put the code you would have put in the `run` loop here 

    def doSomething(self):
        pass

    def doSomethingElse(self):
        pass

下面是组合的想法代码。基本上,我希望生成一个线程,然后将要执行的函数排队,在本例中是reboot()。reboot()依次创建两个线程,powerDown()和powerUp()线程,其中powerDown()在powerUp()上挂起

import threading
import Queue

class Server(threading.Thread):
    def __init__(self, q, loop_time = 1.0/60):
        self.q = q
        self.timeout = loop_time
        super(Server, self).__init__()

    def run(self):
        while True:
            try:
                function, args, kwargs = self.q.get(timeout=self.timeout)
                function(*args, **kwargs)
            except queue.Empty:
                self.idle()

    def idle(self):
        # put the code you would have put in the `run` loop here 

    # This is the top level function called by other objects
    def reboot(self):
        self.__onthread(self.__reboot)

    def __reboot(self):
        if not hasattr(self, "_down"):
            self._down = threading.Thread(target=self.__powerDown)
            self._down.start()
            up = threading.Thread(target=self.__powerUp)
            up.start()

    def __onThread(self, function, *args, **kwargs):
        self.q.put((function, args, kwargs))

    def __powerDown(self):
        # do something

    def __powerUp(self):
        if not hasattr(self, "_down"):
            return
        self._down.join()
        # do something
        del self._down

除了我创建两个服务器子类之外,其他都可以。你知道吗

class ServerA(Server):
    pass

class ServerB(Server):
    pass

下面是一段代码,用于初始化这两个子类,并调用start()和reboot函数

serverA = ServerA(None)
serverB = ServerB(None)
serverA.start()
serverB.start()
serverA.reboot()
serverB.reboot()

我想服务器A.重新启动()和服务器B.重新启动()同时发生,这是我想要的,但他们没有!服务器B.重新启动()在之后执行服务器A.重新启动()已完成。也就是说,如果我把打印报表

serverA started
serverB started
serverA.reboot() called
serverA.__powerDown called
serverA.__powerUp called
serverB.reboot() called
serverB.__powerDown called
serverB.__powerUp called

我知道ServerA需要更长的时间才能重新启动,所以我期望类似这样的事情

serverA started
serverB started
serverA.reboot() called
serverB.reboot() called
serverA.__powerDown called
serverB.__powerDown called
serverB.__powerUp called
serverA.__powerUp called

我希望这是有道理的。如果是这样,为什么我的reboot()函数不能同时执行?你知道吗


Tags: theselfdefargsfunctionthreadkwargsdown
1条回答
网友
1楼 · 发布于 2024-10-03 11:25:06

当您首先需要一个queue对象时,为什么要发送None?这将导致一个异常,该异常抱怨None type对象没有get方法。此外,您希望在run方法中处理的异常是Queue.Empty,而不是queue.Empty。你知道吗

下面是修改后的代码及其在我的机器上的输出:

import threading
import Queue

class Server(threading.Thread):
    def __init__(self, title, q, loop_time = 1.0/60):
        self.title = title
        self.q = q
        self.timeout = loop_time
        super(Server, self).__init__()

    def run(self):
        print "%s started" % self.title
        while True:
            try:
                function, args, kwargs = self.q.get(timeout=self.timeout)
                function(*args, **kwargs)

            except Queue.Empty:
                # print "empty"
                self.idle()

    def idle(self):
        pass
        # put the code you would have put in the `run` loop here 

    # This is the top level function called by other objects
    def reboot(self):
        self.__onThread(self.__reboot)

    def __reboot(self):
        if not hasattr(self, "_down"):
            self._down = threading.Thread(target=self.__powerDown)
            self._down.start()
            up = threading.Thread(target=self.__powerUp)
            up.start()

    def __onThread(self, function, *args, **kwargs):
        self.q.put((function, args, kwargs))

    def __powerDown(self):
        # do something
        print "%s power down" % self.title
        pass

    def __powerUp(self):
        print "%s power up" % self.title

        if not hasattr(self, "_down"):
            return

        self._down.join()
        # do something
        del self._down

class ServerA(Server):
    pass

class ServerB(Server):
    pass

def main():
    serverA = ServerA("A", Queue.Queue())
    serverB = ServerB("B", Queue.Queue())
    serverA.start()
    serverB.start()
    serverA.reboot()
    serverB.reboot()

if __name__ == '__main__':
    main()

输出:

A started
B started

B power down
A power down
B power up
A power up

相关问题 更多 >