Thread(스레드)란 무엇인가?(2) – Python Threading Module

이전 thread 설명 보기

[[Python] Thread(스레드)란 무엇인가?(1)](https://velog.io/@grayson1999/Python-Thread%EC%8A%A4%EB%A0%88%EB%93%9C%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%801-%EB%93%B1%EC%9E%A5-%EB%B0%B0%EA%B2%BD)

1. Threading Module

1.1. Thread 실행 방법

쓰레드를 사용하는 방법은 두 가지가 있다.

  1. 서브 클래스에서 run() 메서드를 재정의하는 방법
  2. target에 콜러블 객체를 전달하는 방법

하나씩 알아보자.

1.2. 서브 클래스에서 run() 메서드 재정의

먼저 상속이라는 개념을 이해해야 한다. 상속은 부모 클래스(super class)에서 속성과 메서드를 자식 클래스(sub class)로 물려주는 것을 의미한다. 부모 클래스에 있는 메서드는 자식 클래스에서도 사용할 수 있고, 자식 클래스에서 부모 클래스의 메서드를 재정의하거나 기능을 추가할 수 있다.

아래는 서브 클래스에서 run() 메서드를 재정의하는 방법이다.

import threading
import time

class Worker(threading.Thread):
    def __init__(self, name):
        super().__init__()
        self.name = name

    def run(self):
        print("서브 스레드 시작", threading.currentThread().getName())
        time.sleep(1)
        print("서브 스레드 종료", threading.currentThread().getName())

for i in range(3):
    name = "comgong_stone {}".format(i)
    t = Worker(name)
    t.start()

위 코드를 보면 Worker 클래스는 threading.Thread를 상속받고 있다. 이 클래스에서 __init__()run() 메서드를 재정의하여 첫 번째 쓰레드를 실행하는 방법을 보여준다.

재정의할 때 주의해야 할 점은 __init__()run() 메서드만 수정해야 한다는 것이다. 다른 메서드는 재정의하면 안 된다.

1.3. target에 콜러블 객체 전달하기

이 방법은 가장 흔히 사용된다. 코드를 보면서 설명할게.

from threading import Thread
import time

def addition_operation(work_id, start, end, result):
    print(f'작업 단위: {work_id}')
    total = 0
    for i in range(start, end):
        total += i
        time.sleep(0.001)
    result.append(total)

result_list = []
start, end = 0, 1000  # 1천
thread1 = Thread(target=addition_operation, args=(1, start, end // 2, result_list))
thread2 = Thread(target=addition_operation, args=(2, end // 2, end, result_list))

위 코드에서 Thread에 매개변수를 지정해 전달하는 방법을 사용하고 있다. 원하는 실행을 위해 사용자 함수로 정의하고, 정의한 함수를 target을 통해 넘겨준다.

2. Class Thread의 매개변수

Thread 클래스의 매개변수는 다음과 같다.

Thread(group=None, target=None, name=None, args=(), kwargs={}, *, daemon=None)

각 인자는 다음과 같은 목적을 가진다.

  • group: ThreadGroup 클래스 구현 시 향후 확장을 위해 예약됨.
  • target: run() 함수를 통해 실행할 함수를 지정한다. 콜러블 객체를 인자로 받는다.
  • args: target으로 지정한 함수의 args 파라미터 값을 iterable한 객체로 받는다.
  • kwargs: target으로 지정한 함수의 kwargs 파라미터 값을 dict 객체로 받는다.
  • name: Thread 객체의 이름을 정한다. 기본적으로 “Thread-N” 형태의 고유한 이름이 지정된다. (N은 숫자)
  • daemon: Thread를 Daemon Thread로 만들고 싶을 때 사용한다.

group은 예약된 값이므로 None만 받을 수 있다.

target은 쓰레드를 생성할 함수를 지정하는 매개변수이고, argskwargs는 실행해야 하는 함수에 값을 넘겨주는 역할을 한다.

예를 들어, 아래와 같은 함수가 있을 때, line 매개변수를 넘겨주어야 제대로 실행된다.

def print_comgong(line):
    for _ in range(5):
        print(line)

args는 iterable한 객체를 받고, kwargs는 dict 객체를 받는다. 대표적인 iterable 타입으로는 list, dict, set, str, bytes, tuple, range가 있다.

name은 쓰레드의 이름을 지정하는 데 사용되며, 아무것도 지정하지 않으면 중복되지 않은 이름이 자동으로 부여된다.

daemon은 Daemon Thread를 만들 때 사용하며, True로 설정하면 Daemon Thread가 된다. Daemon 쓰레드는 일반 쓰레드의 작업을 보조하는 역할을 한다. 일반 쓰레드는 각각의 쓰레드가 종료되어도 다른 쓰레드에 영향을 미치지 않지만, Daemon 쓰레드는 모든 일반 쓰레드가 종료되면 강제 종료된다. 그래서 Daemon 쓰레드는 자동 저장, 화면 자동 갱신 등의 보조 역할을 수행한다.

다음은 주요 메서드에 대해 실습과 함께 알아보겠다.

참고 자료

위로 스크롤