Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/362.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 从线程派生线程_Python_Multithreading - Fatal编程技术网

Python 从线程派生线程

Python 从线程派生线程,python,multithreading,Python,Multithreading,我正在使用python 3.4.2来 让线程列表中的线程(t1)处理一些数据 让t1生成另一个线程(t2)来执行额外的处理 问题在于,似乎正确调用了proc\u q1并添加了t2\u q ID,但t2线程在exit\u标志设置为True之前没有从队列中拾取任务。为什么proc_q2从未被调用过 这里有一些模拟代码 import urllib.request import threading from queue import Queue from xml.etree import Elemen

我正在使用python 3.4.2来

  • 让线程列表中的线程(t1)处理一些数据
  • 让t1生成另一个线程(t2)来执行额外的处理
  • 问题在于,似乎正确调用了
    proc\u q1
    并添加了t2\u q ID,但t2线程在
    exit\u标志设置为
    True
    之前没有从队列中拾取任务。为什么
    proc_q2
    从未被调用过

    这里有一些模拟代码

    import urllib.request
    import threading
    
    from queue import Queue
    from xml.etree import ElementTree as ET
    from urllib.parse import urlparse
    
    class Scanner(object):
        @staticmethod
        def proc_q1(thread_id, q1, q2):
            while not exit_flag:
                t1_lck.acquire()
                if not q1.empty():
                    new_id = q1.get()
                    t1_lck.release()
                    # add id to t2_queue for threads2 to pick up
                    t2_lck.acquire()
                    t2_q.put(new_id)
                    t2_lck.release()
                    print('proc_q1 - new_id: {}'.format(new_id))
                else:
                    t1_lck.release()
    
        @staticmethod
        def proc_q2(thread_id, q):
            t2_lck.acquire()
            if not q.empty():
                new_id = q.get()
                t2_lck.release()
                print('proc_q2 - new_id: {}'.format(new_id))
            else:
                t2_lck.release()
    
    
    class MyT1(threading.Thread):
        def __init__(self, thread_id, q1, q2):
            threading.Thread.__init__(self)
            self.thread_id = thread_id
            self.q1 = q1
            self.q2 = q2
    
        def run(self):
            print('Starting t1-thread {}'.format(self.thread_id))
            Scanner.proc_q1(thread_id=self.thread_id, q1=self.q1, q2=self.q2)
            print('Exiting t1-thread {}'.format(self.thread_id))
    
    
    class MyT2(threading.Thread):
        def __init__(self, thread_id, q):
            threading.Thread.__init__(self)
            self.thread_id = thread_id
            self.q = q
    
        def run(self):
            print('Starting t2-thread {}'.format(self.thread_id))
            Scanner.proc_q2(thread_id=self.thread_id, q=self.q)
            print('Exiting t2-thread {}'.format(self.thread_id))
    
    # Create new threads
    thread_pool_size = 5
    t1_list = list()
    t2_list = list()
    t1_q = Queue(2 * thread_pool_size)
    t2_q = Queue(2 * thread_pool_size)
    t1_lck = threading.Lock()
    t2_lck = threading.Lock()
    
    exit_flag = False
    
    for i in range(thread_pool_size):
        t1 = MyT1(thread_id=i, q1=t1_q, q2 = t2_q)
        t1.start()
        t1_list.append(t1)
    
        t2 = MyT2(thread_id=i, q=t2_q)
        t2.start()
        t2_list.append(t2)
    
    # put data on the queue
    t1_lck.acquire()
    for i in range(10):
        t1_q.put(i)
    t1_lck.release()
    
    # Wait for empty queue
    while not (t1_q.empty() and t2_q.empty()):
        pass
    
    exit_flag = True
    
    # wait for threads2 to finish
    for t in t2_list:
        t.join()
    
    # wait for threads1 to finish
    for t in t1_list:
        t.join()
    
    print("Done")
    
    这是输出(脚本没有正确退出)


    我认为日志输出给出了答案

    MyT2线程在队列q2中的线程被填充之前退出

    退出条件为:

    @staticmethod
    def proc_q2(thread_id, q):
        ...
        if not q.empty():
        ...
    
    最初,队列q2是空的,因此在队列有数据之前,all MyT2退出

    因此,程序将永远在while循环中循环:

    ...
    while not (t1_q.empty() and t2_q.empty()):
    ...
    
    顺便说一句: 锁定:据我所知,队列的get()和put()方法是同步的。排队和解排队不需要获取锁

    从文档中:


    仅就您的主题发表评论:每个(!)进程都包含一个线程,它是最初运行的线程。没有此线程,您将无法执行任何操作,包括启动其他线程。顺便说一句,第一个线程通常并不特别。关于您的代码:它太长了,需要依赖外部服务来访问URL和下载内容。根据指导原则,用mock替换此代码以生成所需的最小示例。@UlrichEckhardt,我用mock更新了提供的代码。它仍然很长,但更易于管理。感谢您提供的可读性指导。
    ...
    while not (t1_q.empty() and t2_q.empty()):
    ...
    
    17.7. queue — A synchronized queue class