使用 10 个线程打印升序数字
Print ascending numbers using 10 threads
最近我偶然发现了一个为软件工程师设计的面试问题。问题是:
给定 10 个线程,按顺序打印 1-100,以便线程 1 打印 1、11、21 等 (Python)
无论如何我都不是 Python 方面的专家,但我认为解决方案应该非常简单。然而,我连续 3 个小时都无法解决这个问题,这让我很困惑。到目前为止我想出的代码如下:
import threading, queue
THREADS_NUM = 10
LIMIT = 100
class MyThread(threading.Thread):
lock = threading.Lock()
def __init__(self, q):
threading.Thread.__init__(self)
MyThread.lock.acquire()
self.id = int(self.name[7:])
#print("My id is %d" % self.id)
self.q = q
MyThread.lock.release()
def run(self):
MyThread.lock.acquire()
while True:
try:
#print("Right now the queue size is %d" % self.q.qsize())
current_num = self.q.get()
if current_num % 10 == self.id:
print("%s is now printing %d" % (self.id, current_num))
else:
self.q.put(current_num)
except queue.Empty:
print("reached the end")
break
finally:
self.q.task_done()
MyThread.lock.release()
#threads = []
q = queue.Queue()
for i in range(1, LIMIT):
q.put(i)
for i in range(1, THREADS_NUM):
thread = MyThread(q)
#threads.append(thread)
thread.start()
q.join()
#for t in threads:
# t.join()
经过一番研究后,我发现最简单的选择是使用默认可用的同步 queue 和 threading 库在 python3 中。这个问题没有说明 library/method 我应该使用什么,所以我愿意接受其他方法。
注意
此代码打印:
1 is now printing 1
1 is now printing 11
1 is now printing 21
1 is now printing 31
1 is now printing 41
1 is now printing 51
1 is now printing 61
1 is now printing 71
1 is now printing 81
1 is now printing 91
...hangs & never exits
好吧,如果我能在我的评论中实现这个想法,我很好奇,它似乎:
#!/usr/bin/env python3.7
import threading
THREADS_NUM = 10
LIMIT = 100
class NumberPrinterThread(threading.Thread):
def __init__(self, mod_n, initial):
super().__init__()
self.mod_n = mod_n
self.n = initial
self.e = threading.Event()
self.next_event = None
def run(self):
while True:
# Wait to be told to print
self.e.wait()
# Clear/reset our own event
self.e.clear()
print(self.n)
# Signal the next thread to print
self.next_event.set()
# Exit if the next number is too big
self.n += self.mod_n
if self.n > LIMIT:
return
if __name__ == "__main__":
threads = [NumberPrinterThread(THREADS_NUM, n + 1) for n in range(THREADS_NUM)]
for i, t in enumerate(threads):
# Link each thread to the next
next_thread = threads[(i + 1) % THREADS_NUM]
t.next_event = next_thread.e
for t in threads:
t.start()
# Signal the first thread
threads[0].e.set()
for t in threads:
t.join()
最近我偶然发现了一个为软件工程师设计的面试问题。问题是:
给定 10 个线程,按顺序打印 1-100,以便线程 1 打印 1、11、21 等 (Python)
无论如何我都不是 Python 方面的专家,但我认为解决方案应该非常简单。然而,我连续 3 个小时都无法解决这个问题,这让我很困惑。到目前为止我想出的代码如下:
import threading, queue
THREADS_NUM = 10
LIMIT = 100
class MyThread(threading.Thread):
lock = threading.Lock()
def __init__(self, q):
threading.Thread.__init__(self)
MyThread.lock.acquire()
self.id = int(self.name[7:])
#print("My id is %d" % self.id)
self.q = q
MyThread.lock.release()
def run(self):
MyThread.lock.acquire()
while True:
try:
#print("Right now the queue size is %d" % self.q.qsize())
current_num = self.q.get()
if current_num % 10 == self.id:
print("%s is now printing %d" % (self.id, current_num))
else:
self.q.put(current_num)
except queue.Empty:
print("reached the end")
break
finally:
self.q.task_done()
MyThread.lock.release()
#threads = []
q = queue.Queue()
for i in range(1, LIMIT):
q.put(i)
for i in range(1, THREADS_NUM):
thread = MyThread(q)
#threads.append(thread)
thread.start()
q.join()
#for t in threads:
# t.join()
经过一番研究后,我发现最简单的选择是使用默认可用的同步 queue 和 threading 库在 python3 中。这个问题没有说明 library/method 我应该使用什么,所以我愿意接受其他方法。
注意
此代码打印:
1 is now printing 1
1 is now printing 11
1 is now printing 21
1 is now printing 31
1 is now printing 41
1 is now printing 51
1 is now printing 61
1 is now printing 71
1 is now printing 81
1 is now printing 91
...hangs & never exits
好吧,如果我能在我的评论中实现这个想法,我很好奇,它似乎:
#!/usr/bin/env python3.7
import threading
THREADS_NUM = 10
LIMIT = 100
class NumberPrinterThread(threading.Thread):
def __init__(self, mod_n, initial):
super().__init__()
self.mod_n = mod_n
self.n = initial
self.e = threading.Event()
self.next_event = None
def run(self):
while True:
# Wait to be told to print
self.e.wait()
# Clear/reset our own event
self.e.clear()
print(self.n)
# Signal the next thread to print
self.next_event.set()
# Exit if the next number is too big
self.n += self.mod_n
if self.n > LIMIT:
return
if __name__ == "__main__":
threads = [NumberPrinterThread(THREADS_NUM, n + 1) for n in range(THREADS_NUM)]
for i, t in enumerate(threads):
# Link each thread to the next
next_thread = threads[(i + 1) % THREADS_NUM]
t.next_event = next_thread.e
for t in threads:
t.start()
# Signal the first thread
threads[0].e.set()
for t in threads:
t.join()