본문 바로가기
개발 이야기/Python

Multi Thread 결과 값 리턴하여 저장하기

by _ppuing 2021. 7. 22.
반응형

Thread는 보통 현재 메인 Thread 에서 시간을 더 이상 잡아먹지 않기 위해 비동기적으로 작업을 넘겨버리고 주 작업을 하고 싶을 때 사용한다. 따라서 이런 경우는 그렇게 생성한 Thread의 결과가 어떤지 살펴볼 필요가 없을 때이다. 예를 들어, 고객 주문 처리 함수를 구현한다고 가정하면, 고객 주문을 완료 하고 마지막에 고객에게 알림 메시지를 발송하는 기능을 구현한다고 하자. 

 

고객에게 알림 메시지를 발송하기 위해 타 업체의 API를 이용해야 하는데, 만약 타 업체 서버가 점검 중이어서 타임아웃 30초 동안 리스폰스를 받지 못한다면 해당 주문 처리 함수는 30초 동안 진행이 되지 않는다. 따라서 이런 경우에 알림의 성공 유무와 관계 없이 일단 주문처리를 완료하고 싶을 때 Thread를 이용할 수 있다. 

 

반면 Multi Thread 기반의 프로그래밍을 하다보면 각각의 Thread가 리턴하는 값을 모아서 확인하고 싶은 경우가 있다. 10만회의 반복문을 돌리기 위해 단일 Thread (메인 Thread만 사용) 로 구현할 때 반복 횟수가 너무 많아 성능이 떨어질 수 있으므로 5개의 Thread만 만들어도 각각이 2만 개의 루프만 돌아도 되니 훨씬 효율적일 것이다. 

보통 Thread는 아래와 같이 사용하는데, 

import threading

def f(v):
    """
    :param v: {"input": 특정 값, "output": None}
    :return: 계산 결과를 포함한 object
    """
    v["output"] = 3 + v["input"]
    return v

variables = [{"input": 1}, {"input": 5}, {"input": 3}, {"input": 2} , {"input": 9}]
threads = []

for var in variables:
    t = threading.Thread(target=f, args=(v,))
    t.start()
    threads.append(t)
    
for t in threads:
    t.join()
    
>>> 메인 스레드 : 그래서 각 결과가 뭐야 ?

위 코드는 어떤 변수를 받으면 3씩 더해주고 각 Dict의 output에 값을 저장하는 함수이다. Thread를 사용하면 거의 동시에 가깝게 5개의 리스트 계산이 완료된다. 그런데 return x 를 해줘도, 각 결과들은 타 thread에서 완료된 결과이기 때문에 메인 Thread 에서는 결과를 알 수가 없다. 

 

만약 계산 결과들을 다시 모아서 확인하고 싶은 경우를 위해 Thread 클래스를 상속 받아서 결과를 저장하도록 만들 수 있는데, Queue 를 사용하면 굳이 새 클래스를 만들지 않고 해결이 가능하다. 

 

import threading
import Queue

q = Queue.Queue()

def f(v, queue):
    """
    :param v: {"input": 특정 값, "output": None}
    :param queue: 계산 결과를 저장할 queue
    """
    v["output"] = 3 + v["input"]
    queue.put(v)

variables = [{"input": 1}, {"input": 5}, {"input": 3}, {"input": 2} , {"input": 9}]
threads = []

for var in variables:
    t = threading.Thread(target=f, args=(v, q,))
    t.start()
    threads.append(t)
    
for t in threads:
    t.join()
    
print list(q.queue)

>>> 메인 스레드 : 결과는 아래와 같음
[
    {"input": 1, "output": 4},
    {"input": 9, "output": 12},
    {"input": 5, "output": 8},
    {"input": 2, "output": 5},
    {"input": 3, "output": 6},
]

 

반응형

댓글