需求:在Python-主线程控制子线程结束-2的基础上,添加在子线程中执行操作并获取结果的功能。
一种常见的方法是使用队列(Queue)或者共享变量,在子线程中存储结果,然后在主线程中获取这些结果。这种方法可以确保线程间的数据共享是线程安全的。
# 修改后的程序,主线程可以获取子线程的结果
import threading
import time
import queue
from loguru import logger
exit_program = False
class WorkerThread(threading.Thread):
def __init__(self, result_queue):
super().__init__()
self.stop_event = threading.Event()
self.result_queue = result_queue
static_variable = 0
def run(self):
thread_id = threading.get_ident()
print(f"Worker thread {thread_id} has started.")
while not self.stop_event.is_set():
print(f"Worker thread {thread_id} is running.")
# Simulate some work
result = self.do_work()
self.result_queue.put(result)
time.sleep(1)
print(f"Worker thread {thread_id} has stopped.")
def increment_static_variable(cls):
cls.static_variable += 1
def do_work(self):
# Simulate some work
self.increment_static_variable()
return self.static_variable
def stop(self):
self.stop_event.set()
self.join() # 等待子线程结束
def end_child_thread():
try:
if worker_thread.is_alive():
worker_thread.stop()
logger.info(f"Stopping worker thread {worker_thread.ident}...")
if worker_thread.is_alive():
logger.info(f"Worker thread {worker_thread.ident} is still active")
else:
logger.info(f"Worker thread {worker_thread.ident} doesn't exist ..")
except Exception as e:
logger.info("中止线程失败:" + e)
def key_listener():
keyboard_thread_id = threading.get_ident() # 获取键盘监听线程的ID
global worker_thread # 声明为全局变量
# global result_queue
print("""
Press '0' to stop worker thread,
'1' to start a new worker thread,
'2' to end the program.
...""")
while True:
print(f"Keyboard listener thread {keyboard_thread_id} has started.")
command = input("请输入指令~")
if command == '0':
logger.info(f"工作线程状态{worker_thread}")
end_child_thread()
logger.info(f"工作线程状态{worker_thread}")
elif command == '1':
try:
if worker_thread.is_alive():
pass
else:
worker_thread = WorkerThread(result_queue)
worker_thread.start()
logger.info(f"Started new worker thread {worker_thread.ident}")
except Exception as e:
logger.info("新建工作线程失败:" + e)
elif command == '2':
end_child_thread()
global exit_program
exit_program = True
break
else:
pass
time.sleep(0.1)
if __name__ == '__main__':
result_queue = queue.Queue()
main_thread_id = threading.main_thread().ident
logger.info(f"Main thread {main_thread_id} has started~")
worker_thread = WorkerThread(result_queue)
keyboard_thread = threading.Thread(target=key_listener) # 创建键盘输入监听线程
keyboard_thread.start() # 启动键盘输入监听线程
worker_thread.start()
logger.info(f"Keyboard monitor thread {keyboard_thread.ident} has started~")
logger.info(f"worker thread {worker_thread.ident} has started~")
try:
while not exit_program:
if not result_queue.empty():
result = result_queue.get()
print("主线程获取的子线程结果:", result)
else:
# print("Main thread didn't get any result")
pass
except:
print("手动停止程序...")
worker_thread.stop() # 在主线程退出时停止子线程
worker_thread.join() # 等待子线程结束
print('exit')
# 主线程退出
logger.info(f"Main thread {main_thread_id} is exiting~")