多线程需求:Python3.x(Ubuntu16.04)下监控数据流动态启停线程
Hey there! Let's walk through implementing this integer data stream monitoring system with Python 3 on Ubuntu 16.04, and also outline how to add the Tkinter GUI later.
First off, a critical note: never force-terminate threads in Python (it's unsafe and can leave resources in a broken state). Instead, we'll use a thread-safe flag (like threading.Event()) to signal the recording thread to exit gracefully when the data drops below 5.
Here's a working code example that simulates a data stream and handles the thread lifecycle:
import threading import time import random # Track the active recording thread and stop signal recording_thread = None stop_recording = threading.Event() def record_data(): """Thread function to continuously record data until stop signal is triggered""" print("Recording thread started") while not stop_recording.is_set(): # Replace this with your actual data recording logic (file write, DB insert, etc.) current_data = get_current_data() print(f"Recording data: {current_data}") time.sleep(0.5) # Simulate recording interval print("Recording thread terminated gracefully") def get_current_data(): """Simulate your integer data stream - replace with real data source""" return random.randint(0, 10) def monitor_stream(): """Main monitoring loop that checks data and manages the recording thread""" global recording_thread, stop_recording while True: data = get_current_data() print(f"Current data: {data}") if data >= 5 and recording_thread is None: # Reset stop signal and start new recording thread stop_recording.clear() recording_thread = threading.Thread(target=record_data, daemon=True) recording_thread.start() elif data < 5 and recording_thread is not None: # Trigger stop signal and wait for thread to exit stop_recording.set() recording_thread.join() recording_thread = None time.sleep(1) # Adjust monitoring interval as needed if __name__ == "__main__": try: monitor_stream() except KeyboardInterrupt: # Clean up on exit if recording_thread is not None: stop_recording.set() recording_thread.join() print("\nMonitoring stopped")
Key points here:
- We use
threading.Event()to safely signal the recording thread to stop - The recording thread checks the event in its loop and exits gracefully
- We track the active recording thread to avoid starting multiple threads when data stays ≥5
- Daemon threads ensure they exit automatically if the main thread is interrupted
Since you already have a separate thread for your process counter, make sure to use thread-safe operations when updating or reading the counter value to avoid corruption. For example:
# Add a thread-safe counter and lock counter = 0 counter_lock = threading.Lock() def counter_thread(): """Your existing counter thread - updated for thread safety""" global counter while True: with counter_lock: counter += 1 print(f"Process counter: {counter}") time.sleep(2) # Start the counter thread in your main block if __name__ == "__main__": threading.Thread(target=counter_thread, daemon=True).start() try: monitor_stream() # ... rest of the exit cleanup code
Using threading.Lock() ensures that concurrent reads/writes from multiple threads don't corrupt the counter value.
To add a Tkinter interface without blocking the monitoring logic, you'll need to run the monitoring loop using Tkinter's after() method (instead of a blocking while True loop). Here's a rough outline:
import tkinter as tk from tkinter import scrolledtext class DataMonitorGUI: def __init__(self, root): self.root = root self.root.title("Data Stream Monitor") # GUI Elements self.data_label = tk.Label(root, text="Current Data: --", font=("Arial", 12)) self.data_label.pack(pady=5) self.status_label = tk.Label(root, text="Status: Idle", font=("Arial", 10), fg="gray") self.status_label.pack(pady=5) self.log_text = scrolledtext.ScrolledText(root, width=50, height=10) self.log_text.pack(pady=10) # Thread management variables self.recording_thread = None self.stop_recording = threading.Event() # Start non-blocking monitoring self.monitor_stream() def log_message(self, msg): """Thread-safe method to update GUI log""" self.log_text.insert(tk.END, f"{msg}\n") self.log_text.see(tk.END) def record_data(self): """Recording thread function with GUI updates""" self.log_message("Recording started") self.status_label.config(text="Status: Recording", fg="green") while not self.stop_recording.is_set(): current_data = get_current_data() self.log_message(f"Recorded: {current_data}") time.sleep(0.5) self.log_message("Recording stopped") self.status_label.config(text="Status: Idle", fg="gray") def monitor_stream(self): """Non-blocking monitoring loop using Tkinter after()""" data = get_current_data() self.data_label.config(text=f"Current Data: {data}") if data >=5 and self.recording_thread is None: self.stop_recording.clear() self.recording_thread = threading.Thread(target=self.record_data, daemon=True) self.recording_thread.start() elif data <5 and self.recording_thread is not None: self.stop_recording.set() self.recording_thread.join() self.recording_thread = None # Schedule next check after 1 second self.root.after(1000, self.monitor_stream) if __name__ == "__main__": root = tk.Tk() app = DataMonitorGUI(root) # Start counter thread if needed threading.Thread(target=counter_thread, daemon=True).start() root.mainloop()
This setup keeps the GUI responsive because we avoid blocking the main thread, using after() to periodically run the monitoring check.
内容的提问来源于stack exchange,提问作者user9001965

