반응형
PySide6에서 안전하게 멀티스레드 생성 및 관리하기
PySide6에서 UI가 멈추지 않도록 백그라운드에서 여러 개의 작업을 동시에 실행하려면 멀티스레딩(Multithreading) 을 활용해야 합니다. 하지만 멀티스레드를 제대로 관리하지 않으면 데이터 충돌, 성능 저하, 프로그램 충돌과 같은 문제가 발생할 수 있습니다. 이 글에서는 멀티스레드의 개념을 설명하고, PySide6에서 QThreadPool과 QRunnable을 사용하여 안전하게 멀티스레드를 생성하고 관리하는 방법을 설명합니다.
1. 멀티스레드란?
🔍 멀티스레드 개념 쉽게 이해하기
멀티스레딩(Multithreading)이란 하나의 프로그램 내에서 여러 개의 스레드를 실행하여 동시에 여러 작업을 수행하는 기술입니다.
🖥️ 멀티스레드의 실생활 예시
- 웹 브라우저: 여러 개의 탭을 동시에 로드하고 사용자가 입력을 할 수 있음.
- 비디오 스트리밍 앱: 영상 재생 중에도 네트워크에서 데이터를 지속적으로 다운로드함.
- 게임: 그래픽 렌더링, AI 연산, 사용자 입력 처리 등이 동시에 수행됨.
- 파일 다운로드 관리자: 여러 개의 파일을 동시에 다운로드함.
- 데이터 처리 프로그램: 여러 개의 CPU 코어를 활용하여 연산 속도를 높임.
⚠️ 멀티스레드 사용 시 주의할 점
- 여러 개의 스레드가 공유 자원(예: 리스트, 딕셔너리)을 수정할 경우 데이터 충돌이 발생할 수 있음.
- 너무 많은 스레드를 생성하면 CPU 사용량이 증가하여 오히려 성능이 저하될 수 있음.
- UI 업데이트는 반드시 메인 스레드에서 실행해야 함.
2. QThreadPool과 QRunnable이란?
🏗 QThreadPool이란?
QThreadPool은 여러 개의 작업을 효율적으로 실행할 수 있도록 스레드 풀(Thread Pool) 을 관리하는 클래스입니다.
- 일반적으로 프로그램에서 실행할 스레드의 개수를 너무 많이 만들면 성능이 저하될 수 있습니다.
- QThreadPool을 사용하면 운영 체제에서 적절한 개수의 스레드를 관리하여 성능을 최적화합니다.
- globalInstance()를 사용하면 전역적으로 사용할 수 있는 QThreadPool을 가져올 수 있습니다.
🎯 QRunnable이란?
QRunnable은 QThreadPool에서 실행할 작업 단위(Task) 를 정의하는 클래스입니다.
- QRunnable을 상속받아 run() 메서드를 구현하면 됩니다.
- QThread처럼 개별적으로 스레드를 생성하는 것이 아니라, QThreadPool을 통해 관리됩니다.
- start(worker)를 호출하면 스레드 풀에서 자동으로 작업을 실행합니다.
3. PySide6에서 멀티스레드를 안전하게 생성하고 관리하는 방법
PySide6에서는 QThread와 QThreadPool을 사용하여 멀티스레드를 구현할 수 있습니다. 일반적으로 여러 개의 단순 작업을 병렬로 실행할 경우 QThreadPool + QRunnable을 사용하는 것이 더 적합합니다.
📌 필요한 모듈
- PySide6.QtCore 모듈: QThread, QThreadPool, QRunnable, Signal
- PySide6.QtWidgets 모듈: UI 구성에 필요한 QApplication, QPushButton, QVBoxLayout, QWidget
4. 예제 코드
다음 예제에서는 QThreadPool과 QRunnable을 활용하여 멀티스레드를 실행하는 방법을 보여줍니다.
반응형
✏️ 코드 설명
- Worker 클래스는 QRunnable을 상속받아 실행됩니다.
- run() 메서드에서 각 스레드가 수행할 작업을 정의합니다.
- QThreadPool을 활용하여 여러 개의 스레드를 관리합니다.
- UI에서 버튼을 눌러 여러 개의 스레드를 실행할 수 있습니다.
import sys
import time
from PySide6.QtCore import QRunnable, QThreadPool, QThread, Signal
from PySide6.QtWidgets import QApplication, QPushButton, QVBoxLayout, QWidget
class Worker(QRunnable):
def __init__(self, task_id):
super().__init__()
self.task_id = task_id
def run(self):
for i in range(5):
print(f"작업 {self.task_id} 실행 중: {i}")
time.sleep(1) # 작업 실행 대기
print(f"작업 {self.task_id} 완료!")
class MainWindow(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setWindowTitle("QThreadPool 멀티스레드 예제")
self.setGeometry(100, 100, 300, 200)
self.button_start = QPushButton("멀티스레드 실행", self)
self.button_start.clicked.connect(self.start_threads)
layout = QVBoxLayout()
layout.addWidget(self.button_start)
self.setLayout(layout)
self.thread_pool = QThreadPool.globalInstance()
def start_threads(self):
for i in range(3): # 3개의 작업 실행
worker = Worker(i)
self.thread_pool.start(worker)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec())
5. 테이블 정리
항목 | 설명 |
QThreadPool | 여러 개의 스레드를 효율적으로 관리하는 클래스 |
QRunnable | 스레드에서 실행할 작업을 정의하는 클래스 |
run() | 각 스레드에서 실행할 작업을 정의하는 메서드 |
start(worker) | 작업을 스레드 풀에서 실행하는 메서드 |
globalInstance() | 전역적으로 사용할 수 있는 QThreadPool 인스턴스 반환 |
반응형
'코딩취미 > Python' 카테고리의 다른 글
multiprocessing.freeze_support() 완벽 가이드 - 동작 원리, 필요성, 예제 코드까지! (0) | 2025.03.01 |
---|---|
파이썬에서 멀티태스킹과 멀티스레드 사용법 (0) | 2025.02.28 |
파이썬에서 안전하게 스레드 멈추기 (0) | 2025.02.28 |
PyInstaller 패키징 시 "모듈을 찾을 수 없음" 오류 해결 방법 (0) | 2025.02.27 |
PySide6로 파일 이동 및 압축하기 – ZIP, TAR, 7Z 압축을 활용한 GUI 프로그램 제작 (0) | 2025.02.27 |