我正在学习一个简单的多线程教程。其中创建了10个线程,对应于处理20个工人。我明白了一个线程是如何处理一个工作线程的,10个线程并行运行,为一个优先级队列中的20个工作线程提供服务。 但我的问题是,如果一个线程已经完成了为指定的工作线程提供服务,而9个线程仍在为其工作线程提供服务,会发生什么情况。你知道吗
我想创建一个脚本,在这个脚本中,如果一个线程的工作结束了,那么它应该获取队列中的其他工作线程。你知道吗
这是我的密码:
import threading
from queue import PriorityQueue
import time
print_lock = threading.Lock()
q = PriorityQueue()
def threader():
i = 0
while True:
worker = q.get()
exampleJob(worker)
q.task_done()
for x in range(10):
t = threading.Thread(target = threader)
t.deamon = True
t.start()
start_time = time.time()
for worker in range(1,20):
q.put(worker)
def exampleJob(worker):
if(worker ==1):
time.sleep(0.5)
else:
time.sleep(5)
with print_lock:
print(threading.current_thread().name,worker)
q.join()
print('Entire job took:', time.time()-start_time)
在上面的代码中,我为worker 1创建了0.5的睡眠时间,但是rest有5秒的睡眠时间,如果我执行这个脚本,线程1将处理worker 1,并等待所有其他9个线程完成它们的worker。 我想如果线程1已经完成了工作,它应该需要11号工人来处理。你知道吗
上述代码的输出为:-
Thread-1 1
Thread-3 3
Thread-5 5
Thread-4 4
Thread-2 2
Thread-6 6
Thread-10 10
Thread-7 7
Thread-9 9
Thread-8 8
Thread-1 11
Thread-3 12
Thread-5 13
Thread-4 14
Thread-2 15
Thread-6 16
Thread-10 17
Thread-7 18
Thread-9 19
Entire job took: 10.137013912200928
您创建了10个线程并启动了每个线程(
for x in range(10):
)。你知道吗每个线程都将尝试从队列中检索对象。由于queue's get method阻塞,实际首先调用
.get()
的第一个线程将阻塞,直到有东西被放入队列。下一个线程将阻塞,直到.get()
返回上一个线程。这是可以保证的,因为队列类的文档说明它是线程安全的。如果一个类或数据结构没有被记录为线程安全的(并且实际上实现得不正确),那么所有的赌注都是无效的。你知道吗请注意,除非您自己显式地编写必要的同步代码(例如使用锁或类似代码),否则线程不能保证顺序。因此不能保证线程1将是第一个真正开始执行并进入
.get()
方法的线程。你知道吗在您启动了10个线程中的每一个之后,您就开始将数字放入队列。当这些数字到达队列时,线程将在某个时候唤醒并接收它们。虽然
PriorityQueue
中的值的顺序是有保证的,但是从队列接收的线程的顺序是没有保证的。你知道吗当它计划运行时,每个线程将在指定的时间内休眠。注意,^{} 对于调用函数和从函数返回之间的实际时间量提供了很少的保证。你知道吗
因此,每个线程都将在前后相同的时间(但不完全相同)开始睡眠,并且将在前后相同的时间醒来,因为睡眠持续时间是相同的,并且被安排在前后相同的时间执行。请注意,线程可以在执行期间的任何时候挂起,另一个线程可以继续。在单核系统上,在任何给定的时间只有一个线程可以实际执行,而所有其他线程都在等待调度程序挂起正在执行的线程并切换到其他线程。在多核系统上,可以在不同的核上同时运行不同的线程,但每个核一次最多运行一个线程。你知道吗
在线程从
.sleep()
返回之后,它们会争着获取锁。这会使每个输出在另一个开始打印之前完成打印。这是一个好的东西,所以输出不会在中间交错。线程获取锁的顺序不能保证。保证一次只有一个线程拥有锁。如果锁可用,那么线程将毫不延迟地获取它,但是如果它不可用,那么它将等待直到它可用为止。你知道吗在您提供的输出中,Thread-1确实处理了“worker”11。不过,这并不能保证,除非您确保在thread-1调用队列上的
.get()
之前,不会启动任何其他线程。在您的程序中,无论哪个线程处理“worker”1,都会处理“worker”11,这是相当可预测的,尽管不能保证,因为睡眠持续时间非常短,很可能它将是队列中的下一个线程,而其他9个线程仍在调用.sleep()
。这是不能保证的,因为调度器可能不会实际调度该线程执行;该线程可能会保持挂起状态,而另一个线程可能会在该线程执行之前到达从队列中检索下一个项目的点。你知道吗希望您提供的程序的这种解释是有帮助的。你知道吗
相关问题 更多 >
编程相关推荐