python多线程同步
我在使用cPython进行线程处理时遇到同步问题。我有两个文件,我解析它们并返回所需的结果。然而,下面的代码行为异常,返回三次而不是两次加号,并没有按照我将它们放入队列的顺序返回。代码如下:python多线程同步,python,multithreading,synchronization,Python,Multithreading,Synchronization,我在使用cPython进行线程处理时遇到同步问题。我有两个文件,我解析它们并返回所需的结果。然而,下面的代码行为异常,返回三次而不是两次加号,并没有按照我将它们放入队列的顺序返回。代码如下: import Queue import threading from HtmlDoc import Document OUT_LIST = [] class Threader(threading.Thread): """ Start threading """ def _
import Queue
import threading
from HtmlDoc import Document
OUT_LIST = []
class Threader(threading.Thread):
"""
Start threading
"""
def __init__(self, queue, out_queue):
threading.Thread.__init__(self)
self.queue = queue
self.out_queue = out_queue
def run(self):
while True:
if self.queue.qsize() == 0: break
path, host = self.queue.get()
f = open(path, "r")
source = f.read()
f.close()
self.out_queue.put((source, host))
self.queue.task_done()
class Processor(threading.Thread):
"""
Process threading
"""
def __init__(self, out_queue):
self.out_queue = out_queue
self.l_first = []
self.f_append = self.l_first.append
self.l_second = []
self.s_append = self.l_second.append
threading.Thread.__init__(self)
def first(self, doc):
# some code to to retrieve the text desired, this works 100% I tested it manually
def second(self, doc):
# some code to to retrieve the text desired, this works 100% I tested it manually
def run(self):
while True:
if self.out_queue.qsize() == 0: break
doc, host = self.out_queue.get()
if host == "first":
self.first(doc)
elif host == "second":
self.second(doc)
OUT_LIST.extend(self.l_first + self.l_second)
self.out_queue.task_done()
def main():
queue = Queue.Queue()
out_queue = Queue.Queue()
queue.put(("...first.html", "first"))
queue.put(("...second.html", "second"))
qsize = queue.qsize()
for i in range(qsize):
t = Threader(queue, out_queue)
t.setDaemon(True)
t.start()
for i in range(qsize):
dt = Processor(out_queue)
dt.setDaemon(True)
dt.start()
queue.join()
out_queue.join()
print '<br />'.join(OUT_LIST)
main()
导入队列
导入线程
从HtmlDoc导入文档
OUT_LIST=[]
类线程器(threading.Thread):
"""
开始穿线
"""
定义初始(自我、队列、输出队列):
threading.Thread.\uuuuu init\uuuuuu(自)
self.queue=队列
self.out\u队列=out\u队列
def运行(自):
尽管如此:
如果self.queue.qsize()==0:break
路径,host=self.queue.get()
f=开放(路径“r”)
source=f.read()
f、 关闭()
self.out_queue.put((源、主机))
self.queue.task_done()
类处理器(threading.Thread):
"""
进程线程
"""
def u u初始(自,出队列):
self.out\u队列=out\u队列
self.l_first=[]
self.f\u append=self.l\u first.append
self.l_秒=[]
self.s\u append=self.l\u second.append
threading.Thread.\uuuuu init\uuuuuu(自)
def优先(自我,文档):
#一些代码来检索所需的文本,这是工作100%我手动测试它
def秒(自我,文档):
#一些代码来检索所需的文本,这是工作100%我手动测试它
def运行(自):
尽管如此:
如果self.out_queue.qsize()==0:break
doc,host=self.out\u queue.get()
如果主机==“第一个”:
自我优先(doc)
elif主机==“秒”:
第二自我(doc)
OUT_LIST.extend(self.l_first+self.l_second)
self.out\u queue.task\u done()
def main():
queue=queue.queue()
out\u queue=queue.queue()
queue.put((“…first.html”,“first”))
queue.put((“…second.html”,“second”))
qsize=queue.qsize()
对于范围内的i(qsize):
t=线程器(队列,输出队列)
t、 setDaemon(True)
t、 开始()
对于范围内的i(qsize):
dt=处理器(输出队列)
dt.setDaemon(True)
dt.start()
queue.join()
out_queue.join()
打印“
”。加入(输出列表)
main()
现在,当我打印时,我想先打印“第一个”的内容,然后打印“第二个”的内容。有人能帮我吗
注意:我正在线程化,因为实际上我一次要连接10多个位置并检索结果。我相信线程是完成这样一项任务的最合适的方式,我不同意线程是最好的方式(我认为一些事件/选择机制会更好),但代码的问题可能在变量t和dt中。您在循环中有赋值,对象实例将存储在任何位置,所以您的线程/处理器的新实例可能在每个循环结束时被删除
如果您向我们展示这段代码的精确输出,会更加清晰。我不同意线程是最好的方法(我认为一些事件/选择机制会更好),但您的代码的问题可能在变量t和dt中。您在循环中有赋值,对象实例将存储在任何位置,所以您的线程/处理器的新实例可能在每个循环结束时被删除 如果您向我们展示此代码的精确输出,将会更加清楚。1)您无法控制作业完成的顺序。它取决于执行时间,所以要想返回所需的结果,您可以使用作业对象(如作业结果)创建全局字典:{'first':None,'second':None}并将结果存储在此处,这样您就可以按所需顺序获取数据 2)
self.first
和self.second
应在每个已处理的单据之后清除,否则您将有重复的输入/输出列表
3) 您可以对子流程模块使用多重处理,例如,将所有结果数据放入CSV文件,并根据需要对其进行排序。1)您无法控制作业完成的顺序。它取决于执行时间,所以要想返回所需的结果,您可以使用作业对象(如作业结果)创建全局字典:{'first':None,'second':None}并将结果存储在此处,这样您就可以按所需顺序获取数据
2) self.first
和self.second
应在每个已处理的单据之后清除,否则您将有重复的输入/输出列表
3) 例如,您可以使用子流程模块的多重处理,将所有结果数据放入CSV文件中,并根据需要对其进行排序
我之所以使用线程,是因为实际上我一次要连接10多个位置并检索结果。我相信线程是完成这项任务最合适的方式
线程实际上是管理多个并发连接最容易出错的方法之一。一种更强大、更可调试的方法是使用事件驱动的异步网络,如由实现的。如果您对使用此模型感兴趣,您可能希望签出
我之所以使用线程,是因为实际上我一次要连接10多个位置并检索结果。我相信线程是完成这项任务最合适的方式
线程实际上是管理多个并发连接最容易出错的方法之一。一种更强大、更可调试的方法是使用事件驱动的异步网络,如由实现的。如果您对使用此模型感兴趣,您可能需要查看。我将多进程优先于多线程,因为同步问题太多,并且当您需要在多台服务器上运行脚本时,可能会有更高的并行级别。绑定I/O的线程很少受到GIL和上下文切换的影响。一根线消耗一根线