- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我的模块中有两个功能:do_something()
, 和 change_behavior()
.
函数do_something()
默认情况下执行 A。后 change_behavior()
已被调用,do_something()
而是做 B 事情。
我希望这种转换是特定于线程的。也就是说,任何新线程在调用 do_something()
时都会发生事件 A。 ,但如果该线程调用 change_behavior()
,那么当 B 继续调用 do_something()
时,它会发生。 .
每个线程应该是独立的,这样一个线程调用 change_behavior()
不影响 do_something()
的行为对于其他线程。
我对此的本能解决方案是将行为与线程的 ID 相关联(通过 threading.get_ident()
评估)。函数do_something()
检查本地表中是否存在线程的 ID,并相应地调整其行为。同时,函数change_behavior()
只需将当前线程添加到该注册表中即可。这在任何给定时间都有效,因为永远不会有两个具有相同 ID 的并发线程。
当当前线程集加入时,问题就出现了,随着时间的流逝,父线程创建了更多线程。新线程之一与先前线程之一具有相同的 ID,因为有时会重复使用线程 ID。该线程调用 do_something()
,并且因为它已经在注册表中,所以它执行的是 B 而不是 A。
为了解决这个问题,我需要以某种方式从注册表中删除线程 ID,在具有该 ID 的第一个线程结束和具有该 ID 的第二个线程开始之间。我提出的一些假设性想法:
change_behavior()
的一部分, 劫持/替换当前线程的 ._quit()
方法首先从注册表中删除线程的 ID。这似乎是不好的做法,并且可能会破坏。 threading.local()
@TarunLalwani 在评论中提出了建议。我已经调查过了,它很有用,但它没有考虑到我想要处理的其他用例 - 当父线程创建新的子线程时,我希望它们继承父线程的状态.我想通过替换
Thread.__init__()
来实现这一点。 ,但使用
local()
通常与此用例不兼容,因为我无法将变量从父线程传递到子线程。
current_thread = threading.current_thread()
setattr(current_thread, my_reference, new_value)
current_thread.my_reference
也设置为
new_value
.我不知道为什么,而且我一直无法在 MVE 中复制这个问题(尽管它在我的 IDE 中一直发生,即使在重新启动它之后)。如
my other currently-active question暗示,我在这里设置的对象是对输出流的引用(我在该答案中描述的对中间 IO 流实例的每个引用都被调用此方法的文件描述符替换),如果有的话与它有关,但我无法想象为什么对象的类型会影响引用在这种情况下的工作方式。
最佳答案
我的回答是对你问题的一个非常简单的回答,因此我想知道我是否遗漏了什么。基本上,我认为您应该避免在模块中存储外部对象的当前状态。
您需要在某处存储状态(如果 change_behavior
被调用,也许还有一些其他数据)。您有两个主要选择:将状态存储在模块中或将状态存储在线程本身中。除了您在模块中存储状态时遇到的问题之外,人们希望模块(主要)是无状态的,因此我认为您应该坚持后者并将数据存储在线程中。
版本 1
如果您将状态存储在字段中,您创建的属性名称和现有属性名称之间会有一点冲突的风险,但是如果文档很清楚并且您选择了一个好的名称,那么这不应该是一个问题。
一个简单的概念证明,没有 setattr
或 hasattr
(我没有检查 CPython 的源代码,但也许奇怪的行为来自 setattr
):
模块1.py
import threading
import random
import time
_lock = threading.Lock()
def do_something():
with _lock:
t = threading.current_thread()
try:
if t._my_module_s:
print(f"DoB ({t})")
else:
print(f"DoA ({t})")
except AttributeError:
t._my_module_s = 0
print(f"DoA ({t})")
time.sleep(random.random()*2)
def change_behavior():
with _lock:
t = threading.current_thread()
print(f"Change behavior of: {t}")
t._my_module_s = 1
import random
import threading
from module1 import *
class MyThread(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
n = random.randint(1, 10)
for i in range(n):
do_something()
change_behavior()
for i in range(10-n):
do_something()
thread_1 = MyThread()
thread_2 = MyThread()
thread_1.start()
thread_2.start()
thread_1.join()
thread_2.join()
DoA (<MyThread(Thread-1, started 140155115792128)>)
DoA (<MyThread(Thread-2, started 140155107399424)>)
DoA (<MyThread(Thread-1, started 140155115792128)>)
DoA (<MyThread(Thread-1, started 140155115792128)>)
Change behavior of: <MyThread(Thread-1, started 140155115792128)>
DoB (<MyThread(Thread-1, started 140155115792128)>)
DoB (<MyThread(Thread-1, started 140155115792128)>)
DoA (<MyThread(Thread-2, started 140155107399424)>)
DoB (<MyThread(Thread-1, started 140155115792128)>)
DoA (<MyThread(Thread-2, started 140155107399424)>)
DoB (<MyThread(Thread-1, started 140155115792128)>)
DoA (<MyThread(Thread-2, started 140155107399424)>)
DoA (<MyThread(Thread-2, started 140155107399424)>)
DoB (<MyThread(Thread-1, started 140155115792128)>)
DoA (<MyThread(Thread-2, started 140155107399424)>)
Change behavior of: <MyThread(Thread-2, started 140155107399424)>
DoB (<MyThread(Thread-2, started 140155107399424)>)
DoB (<MyThread(Thread-1, started 140155115792128)>)
DoB (<MyThread(Thread-1, started 140155115792128)>)
DoB (<MyThread(Thread-2, started 140155107399424)>)
DoB (<MyThread(Thread-2, started 140155107399424)>)
DoB (<MyThread(Thread-2, started 140155107399424)>)
Thread
的所有者子类和您避免名称冲突的风险。另外,在我看来,代码变得更干净了:
import threading
import random
import time
_lock = threading.Lock()
def do_something():
with _lock:
t = threading.current_thread()
t.do_something() # t must be a _UserFunctionWrapper
time.sleep(random.random()*2)
def change_behavior():
with _lock:
t = threading.current_thread()
t.change_behavior() # t must be a _UserFunctionWrapper
def wrap_in_thread(f):
return _UserFunctionWrapper(f)
class _UserFunctionWrapper(threading.Thread):
def __init__(self, user_function):
threading.Thread.__init__(self)
self._user_function = user_function
self._s = 0
def change_behavior(self):
print(f"Change behavior of: {self}")
self._s = 1
def do_something(self):
if self._s:
print(f"DoB ({self})")
else:
print(f"DoA ({self})")
def run(self):
self._user_function()
import random
from module2 import *
def user_function():
n = random.randint(1, 10)
for i in range(n):
do_something() # won't work if the function is not wrapped
change_behavior()
for i in range(10-n):
do_something()
thread_1 = wrap_in_thread(user_function)
thread_2 = wrap_in_thread(user_function)
thread_1.start()
thread_2.start()
thread_1.join()
thread_2.join()
DoA (<_UserFunctionWrapper(Thread-1, started 140193896072960)>)
DoA (<_UserFunctionWrapper(Thread-2, started 140193887680256)>)
DoA (<_UserFunctionWrapper(Thread-2, started 140193887680256)>)
Change behavior of: <_UserFunctionWrapper(Thread-1, started 140193896072960)>
DoB (<_UserFunctionWrapper(Thread-1, started 140193896072960)>)
DoB (<_UserFunctionWrapper(Thread-1, started 140193896072960)>)
DoA (<_UserFunctionWrapper(Thread-2, started 140193887680256)>)
DoA (<_UserFunctionWrapper(Thread-2, started 140193887680256)>)
DoB (<_UserFunctionWrapper(Thread-1, started 140193896072960)>)
DoB (<_UserFunctionWrapper(Thread-1, started 140193896072960)>)
DoA (<_UserFunctionWrapper(Thread-2, started 140193887680256)>)
DoB (<_UserFunctionWrapper(Thread-1, started 140193896072960)>)
DoA (<_UserFunctionWrapper(Thread-2, started 140193887680256)>)
DoB (<_UserFunctionWrapper(Thread-1, started 140193896072960)>)
DoA (<_UserFunctionWrapper(Thread-2, started 140193887680256)>)
DoB (<_UserFunctionWrapper(Thread-1, started 140193896072960)>)
DoA (<_UserFunctionWrapper(Thread-2, started 140193887680256)>)
DoA (<_UserFunctionWrapper(Thread-2, started 140193887680256)>)
Change behavior of: <_UserFunctionWrapper(Thread-2, started 140193887680256)>
DoB (<_UserFunctionWrapper(Thread-2, started 140193887680256)>)
DoB (<_UserFunctionWrapper(Thread-1, started 140193896072960)>)
DoB (<_UserFunctionWrapper(Thread-1, started 140193896072960)>)
关于python - 设置当线程以其他方式完成时要执行的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56959718/
SQLite、Content provider 和 Shared Preference 之间的所有已知区别。 但我想知道什么时候需要根据情况使用 SQLite 或 Content Provider 或
警告:我正在使用一个我无法完全控制的后端,所以我正在努力解决 Backbone 中的一些注意事项,这些注意事项可能在其他地方更好地解决......不幸的是,我别无选择,只能在这里处理它们! 所以,我的
我一整天都在挣扎。我的预输入搜索表达式与远程 json 数据完美配合。但是当我尝试使用相同的 json 数据作为预取数据时,建议为空。点击第一个标志后,我收到预定义消息“无法找到任何内容...”,结果
我正在制作一个模拟 NHL 选秀彩票的程序,其中屏幕右侧应该有一个 JTextField,并且在左侧绘制弹跳的选秀球。我创建了一个名为 Ball 的类,它实现了 Runnable,并在我的主 Draf
这个问题已经有答案了: How can I calculate a time span in Java and format the output? (18 个回答) 已关闭 9 年前。 这是我的代码
我有一个 ASP.NET Web API 应用程序在我的本地 IIS 实例上运行。 Web 应用程序配置有 CORS。我调用的 Web API 方法类似于: [POST("/API/{foo}/{ba
我将用户输入的时间和日期作为: DatePicker dp = (DatePicker) findViewById(R.id.datePicker); TimePicker tp = (TimePic
放宽“邻居”的标准是否足够,或者是否有其他标准行动可以采取? 最佳答案 如果所有相邻解决方案都是 Tabu,则听起来您的 Tabu 列表的大小太长或您的释放策略太严格。一个好的 Tabu 列表长度是
我正在阅读来自 cppreference 的代码示例: #include #include #include #include template void print_queue(T& q)
我快疯了,我试图理解工具提示的行为,但没有成功。 1. 第一个问题是当我尝试通过插件(按钮 1)在点击事件中使用它时 -> 如果您转到 Fiddle,您会在“内容”内看到该函数' 每次点击都会调用该属
我在功能组件中有以下代码: const [ folder, setFolder ] = useState([]); const folderData = useContext(FolderContex
我在使用预签名网址和 AFNetworking 3.0 从 S3 获取图像时遇到问题。我可以使用 NSMutableURLRequest 和 NSURLSession 获取图像,但是当我使用 AFHT
我正在使用 Oracle ojdbc 12 和 Java 8 处理 Oracle UCP 管理器的问题。当 UCP 池启动失败时,我希望关闭它创建的连接。 当池初始化期间遇到 ORA-02391:超过
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 9 年前。 Improve
引用这个plunker: https://plnkr.co/edit/GWsbdDWVvBYNMqyxzlLY?p=preview 我在 styles.css 文件和 src/app.ts 文件中指定
为什么我的条形这么细?我尝试将宽度设置为 1,它们变得非常厚。我不知道还能尝试什么。默认厚度为 0.8,这是应该的样子吗? import matplotlib.pyplot as plt import
当我编写时,查询按预期执行: SELECT id, day2.count - day1.count AS diff FROM day1 NATURAL JOIN day2; 但我真正想要的是右连接。当
我有以下时间数据: 0 08/01/16 13:07:46,335437 1 18/02/16 08:40:40,565575 2 14/01/16 22:2
一些背景知识 -我的 NodeJS 服务器在端口 3001 上运行,我的 React 应用程序在端口 3000 上运行。我在 React 应用程序 package.json 中设置了一个代理来代理对端
我面临着一个愚蠢的问题。我试图在我的 Angular 应用程序中延迟加载我的图像,我已经尝试过这个2: 但是他们都设置了 src attr 而不是 data-src,我在这里遗漏了什么吗?保留 d
我是一名优秀的程序员,十分优秀!