python - 更新传递给线程python的变量
问题描述
我目前遇到的问题与我对线程的理解有关,或者可能是我对如何通过 python 中的线程传递/分配变量的理解。我有一个简单的程序,它接收显示在屏幕上的当前股票列表并获取与这些股票相关的股票信息。我正在使用线程,以便我可以不断更新屏幕并不断收集数据。我有两个问题:
- 在里面
dataCollector_thread()
我明白,如果我附加到里面stocksOnScreenListInfo
的变量(stocksOnScreenListInfo
)main
被更新。
但是我不想附加到列表中,而只是像下面这样重新分配列表,但这不起作用?
def dataCollector_thread(stocksOnScreenListInfo, stocksOnScreen):
while(True):
placeholder = []
for stock in stocksOnScreen:
placeholer.append(RetrieveQuote(stock))
stocksOnScreenListInfo = placeholder
time.sleep(5)
在里面
screenUpdate_thread
我想更新stocksOnScreen
到函数定义的变量'TSLA'UpdateScreen
。当我打印以检查它是否继续说“AAPL”时,这似乎没有更新其对应stocksOnScreen
的内容?main
def main(args): stocksOnScreen = ["AAPL"] # List of the stocks currently displayed on LED screen stocksOnScreenListInfo = [] # The quote information list for each stock on screen thread_data_collector = threading.Thread(target=dataCollector_thread, args=(stocksOnScreenListInfo,stocksOnScreen)) thread_data_collector.daemon = True thread_data_collector.start() thread_screen = threading.Thread(target=screenUpdate_thread, args=(stocksSearchArray,stocksOnScreen)) thread_screen.daemon = True thread_screen.start() def dataCollector_thread(stocksOnScreenListInfo, stocksOnScreen): while(True): for stock in stocksOnScreen: stocksOnScreenListInfo.append(RetrieveQuote(stock)) time.sleep(5) def screenUpdate_thread(stocksSearchArray, stocksOnScreen): while(True): stocksOnScreen = UpdateScreen(stocksSearchArray) def UpdateScreen(stocksSearchArray): pass return ["TSLA"]
解决方案
这个函数有几个问题:
def dataCollector_thread(stocksOnScreenListInfo, stocksOnScreen): while(True): placeholder = [] for stock in stocksOnScreen: placeholer.append(RetrieveQuote(stock)) stocksOnScreenListInfo = placeholder time.sleep(5)
您
stocksOnScreenListInfo
在此函数中分配给一个新列表placeholder
。您要做的是就地修改内容,以便stocksOnScreenListInfo
更新main
。您可以这样做:(stocksOnScreenListInfo[:] = placeholder
这意味着使用新列表从头到尾更改内容)。stocksOnScreen
因为您在另一个线程中更新它,所以在 for 循环中迭代它时可能会发生变化。您应该以原子方式执行此操作。锁(作为 参数传递给函数)在这里会有所帮助:它是一种同步原语,旨在防止在多个线程共享数据并且其中至少一个线程修改它时发生数据竞争。
我看不到stocksOnScreenListInfo
在您的代码中的其他任何地方使用。它是否用于其他功能?如果是这样,您应该考虑锁定它。
我会像这样修改函数:
def dataCollector_thread(stocksOnScreenListInfo, stocksOnScreen, lock):
while True:
placeholder = []
with lock: # use lock to ensure you atomically access stocksOnScreen
for stock in stocksOnScreen:
placeholder.append(RetrieveQuote(stock))
stocksOnScreenListInfo[:] = placeholder # modify contents of stocksOnScreenListInfo
time.sleep(5)
在您的其他线程函数中:
def screenUpdate_thread(stocksSearchArray, stocksOnScreen): while(True): stocksOnScreen = UpdateScreen(stocksSearchArray)
您正在分配stocksOnScreen
给此函数中的新列表;它不会影响stocksOnScreen
in main
。同样,您可以使用符号来做到这一点stocksOnScreen[:] = new_list
。我会在更新之前锁定,stocksOnScreen
以确保您的其他线程函数像这样以原子方式dataCollector_thread
访问:stocksOnScreen
def screenUpdate_thread(stocksSearchArray, stocksOnScreen, lock):
while True:
updated_list = UpdateScreen() # build new list - doesn't have to be atomic
with lock:
stocksOnScreen[:] = updated_list # update contents of stocksOnScreen
time.sleep(0.001)
如您所见,我进入了小睡眠状态,否则该函数将不断循环并且占用大量 CPU。另外,它会让 Python 有机会在线程函数之间进行上下文切换。
最后,在main
创建一个锁:
lock = threading.Lock()
lock
并作为参数传递给这两个函数。
推荐阅读
- python - Snake 一直在循环或重复循环路径移动。尝试使用 NEAT 制作一个在 Python 中玩蛇游戏的 AI
- yii2 - 如何使用 searchmailbox() 通过在此方法的条件中传递日期来搜索电子邮件?
- django - Django-Rest-Framework:通过 Post 请求序列化多对多模型
- angular - 在 Angular SlickGrid 中展开多行会清除之前展开行的行展开视图
- amazon-web-services - 如何与 AWS EC2 实例建立连接并找到托管文件
- django - 在 Django Rest Framework 权限中访问外键值
- react-native - 从 React native Picker selectedvalue 获取参数
- android - Android水平recyclerview自动滚动到中心
- java - 用逗号分隔所有具有非空值的 EditText
- javascript - 特定元素上的 Jquery .map 点击事件