编辑:对代码进行了一些更改,回答了我之前提出的一些问题,但现在我有新问题
我对线程和并行编程非常陌生,所以如果我做了非常规的事情,请原谅我。
我有两个线程,我试图让它们相互通信。其中一个比另一个短,所以我想要的是,当较短的一个结束时,较长的一个也会结束。sentinel
通过传递和扫描某个对象(这里我使用)来标记任一线程的完成,我在这方面取得了部分成功,但我对此有几个问题。这是我正在运行的示例代码:
from threading import Thread
import time
from queue import Queue
sentinel = object()
q = Queue()
q.put(0)
def say_hello(subject, q):
print("starting hello")
for i in range(5):
time.sleep(2)
print(f"\nhello {subject}! iter:{i}")
data = q.get()
if data is sentinel:
break
else:
q.put(data)
print(f"from hello: {q.queue}")
if i == 4:
print("hello finished because of iter")
q.put(sentinel)
else:
print("hello finished because of sentinel from foo")
q.put(sentinel)
def foo(q):
print("starting foo")
for j in range(2):
time.sleep(1)
print(f"\nfoo iter:{j}")
data = q.get()
if data is sentinel:
break
else:
q.put(data)
print(f"from foo: {q.queue}")
if j == 1:
print("foo finished because of iter")
q.put(sentinel)
else:
print("foo finished because of sentinel from hello")
q.put(sentinel)
def t():
print("t:0\n")
for k in range(1,6):
time.sleep(1)
print(f"\nt:{k}")
def run():
time_thread = Thread(target = t)
time_thread.start()
hello_thread = Thread(target = say_hello, args = ["lem", q])
hello_thread.start()
foo_thread = Thread(target = foo, args = [q])
foo_thread.start()
time_thread.join()
hello_thread.join()
foo_thread.join()
print("Done")
run()
在这种情况下,foo
应该先结束,say_hello
然后将结束,这就是从输出中看到的。
这是输出:
t:0
starting hello
starting foo
t:1
foo iter:0
from foo: deque([0])
hello lem! iter:0
t:2
foo iter:1
from foo: deque([0])
foo finished because of iter
from hello: deque([<object object at 0x000001B9CF908EA0>, 0])
t:3
t:4
hello lem! iter:1
hello finished because of sentinel from foo
t:5
Done
现在我的问题是:
- 这是这样做的正确方法吗?是否有一种更简单、更干净、更传统的方法来完成同样的事情?
- 输出似乎有点不稳定,每次我重新运行它时它们都会发生轻微的变化
- 线程之间是否共享同名的局部变量?我之前运行了所有循环
i
,看起来它几乎影响了所有线程 - 似乎
say_hello
并没有完全按照我想要的时间戳运行。那里t:1
不应该有任何输出,say_hello
但确实有。更奇怪的是,这是在's 部分完成from hello: deque...
后才打印的。我一直怀疑他们应该像往常foo
一样成对打印foo
- 有没有一种方法可以让两个线程使用 来查看队列,看看是否有任何内容,如果没有,则跳过它而不会让系统引发错误,而不是
0
在队列的开头包含 a ?.get_nowait()
非常感谢任何和所有的输入。谢谢!