我通过这种方式跟踪信号量的线程数:
#!/usr/bin/python3
import threading
class MyThread(threading.Thread):
max_threads = 5
max_threads_semaphore = threading.BoundedSemaphore(value=max_threads)
semaphore_timeout = 60
def __init__(self, target=None, name=None, args=(), kwargs={}):
super().__init__(target=target, name=name, args=args, kwargs=kwargs)
def start(self):
semaphore_aquired = self.max_threads_semaphore.acquire(blocking=True, timeout=self.semaphore_timeout)
if semaphore_aquired:
print("Sempahore acquired by:", self.name)
super().start()
else:
raise OSError("Time out aquiring max threads semaphore to start new thread")
def join(self):
super().join()
semaphore_released = self.max_threads_semaphore.release()
这项工作,但不是我想要的方式。我希望能够:
def print_test(num):
print("executing:", num)
sleep(10)
print("end of execution:", num)
threads_dict = dict()
thread_range = range(1,20)
for i in thread_range:
threads_dict[i] = MyThread(target=print_test(i))
threads_dict[i].start()
for i in thread_range:
threads_dict[i].join()
print("joined:", threads_dict[i].name)
显然,一旦启动了5个线程(max_threads
),脚本将处于死锁状态,直到达到信号量超时。
我认为start()
方法会在新线程中启动run()
方法。来自the manual:
开始() 每个线程对象最多只能调用一次。它安排 for对象的run()方法在一个单独的线程中调用 控制。
所以在MyThread
中,我将join()
部分替换为:
def run(self):
super().run()
semaphore_released = self.max_threads_semaphore.release()
print("Sempahore released by:", self.name)
但是这个代码不是在新线程中执行的。输出是:
executing: 1
end of execution: 1
Sempahore acquired by: Thread-1
Sempahore released by: Thread-1
executing: 2
end of execution: 2
Sempahore acquired by: Thread-2
Sempahore released by: Thread-2
executing: 3
end of execution: 3
Sempahore acquired by: Thread-3
Sempahore released by: Thread-3
executing: 4
end of execution: 4
Sempahore acquired by: Thread-4
Sempahore released by: Thread-4
executing: 5
end of execution: 5
Sempahore acquired by: Thread-5
Sempahore released by: Thread-5
executing: 6
end of execution: 6
Sempahore acquired by: Thread-6
executing: 7
Sempahore released by: Thread-6
end of execution: 7
Sempahore acquired by: Thread-7
executing: 8
Sempahore released by: Thread-7
end of execution: 8
Sempahore acquired by: Thread-8
executing: 9
Sempahore released by: Thread-8
end of execution: 9
Sempahore acquired by: Thread-9
joined: Thread-1
joined: Thread-2
joined: Thread-3
joined: Thread-4
joined: Thread-5
joined: Thread-6
joined: Thread-7
joined: Thread-8
Sempahore released by: Thread-9
joined: Thread-9
有没有办法重载threading.Thread
函数,以便在目标函数结束时自动释放信号量?
我不明白为什么输出不是:
Sempahore acquired by: Thread-1
executing: 1
Sempahore acquired by: Thread-2
executing: 2
Sempahore acquired by: Thread-3
executing: 3
Sempahore acquired by: Thread-4
executing: 4
Sempahore acquired by: Thread-5
executing: 5
(sleep 10 secondes)
end of execution: 1
Sempahore released by: Thread-1
Sempahore acquired by: Thread-6
executing: 6
etc..
答案 0 :(得分:1)
关于“奇怪”的输出的问题。这是因为您在创建新线程之前在主线程中调用 print_test(i):
threads_dict[i] = MyThread(target=print_test(i))
执行 print_test(i)功能。结果你过去 print_test(i)函数执行的目标结果。
尝试纠正此问题:
threads_dict[i] = MyThread(target=print_test, args=[i,])
经过这次修正后,我的输出如下:
('Sempahore acquired by:', 'Thread-1')
('Sempahore acquired by:', 'Thread-2')
('executing:', 1)
('Sempahore acquired by:', 'Thread-3')
('executing:', 2)
('Sempahore acquired by:', 'Thread-4')
('executing:', 3)
('Sempahore acquired by:', 'Thread-5')
('executing:', 4)
('executing:', 5)
('end of execution:', 1)
('Sempahore released by:', 'Thread-1')
('Sempahore acquired by:', 'Thread-6')
...