공부 목적으로 작성한 것이며 다른 분들의 포스트를 많이 참고했습니다.
concurrent.futures
모듈은 thread와 process에 대해 Pool 기능을 제공한다.Executor
클래스는 함수 호출을 비동기로 디스패치(프로세스가 CPU를 점유하게 되는, 준비 상태에서 실행 상태로 바뀌는 것)하는 역할을 한다.
concurrent.futures는 비동기 병렬 호출을 threadPool, processPool 방식으로 처리하는데 이 pool을 executor이 관리한다.
처리 방식이 thread인지 process인지에 따라 ProcessPoolExecutor
나 ThreadPoolExecutor
를 사용한다.
with ThreadPoolExcutor(max_workers=1) as executor:
future = executor.submit(fn, *args, **kwargs)
print(future.result())
함수와 값을 맵핑하는 map()
함수와 비슷하지만 timeout
인자를 별도로 받으며, 결과값의 순서가 호출된 순서와 동일하지 않다.
future = executor.map(fn, *iterables, timeout=None)
timeout
값을 별도로 주지 않으면 디스패치된 모든 작업들이 종료될 때까지 기다린 후 리턴하며(as_complete()
함수를 사용할 필요 없다), 값이 주어졌을 때 해당 시간 내에 완료되지 못하면 예외를 발생시킨다.
리턴값은 Future 타입이 아닌 결과에 대한 제너레이터이다.
executor에 종료 시그널을 보내 실행중이거나 대기중인 모든 future 객체에 중지 명령을 전달하고 리소스를 정리한다.
shutdown이 호출된 executor에는 map, submit을 호출할 수 없다.
wait
값을 받으며 True인 경우 현재 돌아가고 있는 작업은 중단하지 않고, 대기 중인 작업만 종료된다.
디스패치된 병렬 처리 작업
비동기로 호출된 함수 콜이 객체로 캡슐화된 형태이다. 아직 완료되었는지 모르는 작업을 외부에서 객체로 다룰 수 있다.
API를 통해 작업 완료여부를 확인하거나, 최소, 결과값 fetch 등을 수행할 수 있다.
하나의 작업에 대해 하나 이상의 완료 콜백을 추가할 수 있다.
cancel()
작업 취소를 시도한다. 현재 실행중이고 취소가 불가능한 경우 Fals, 작업이 취소되었으면 True를 리턴한다.
canceled()
취소된 작업이면 True를 리턴한다.
running()
작업이 실행 중인 경우 True를 리턴한다.
result()
해당 호출의 결과를 리턴한다.(병렬 실행시킨 함수의 결과값을 리턴) 작업이 완료되지 않으면 최대 타임아웃 시간까지 기다린 다음 none을 리턴한다.
exception()
해당 호출이 던진 예외를 반환한다. 작업이 완료되지 않으면 최대 타임아웃 시간까지 기다린 다음 none을 리턴한다.
add_done_callback()
콜백함수를 Future 객체에 추가한다. 이 함수는 future 객체 하나를 인자로 받는 함수이다. 콜백은 취소되거나 종료된 경우에 모두 호출된다.
wait()
특정 타임아웃 시간 동안 대기한 다음, 그 시간동안 완료된 작업과 그렇지 않은 작업을 구분하는 2개의 세트로 된 튜플을 리턴한다.
as_completed()
future의 집합을 받아서 기다리면서 하나씩 완료되는 것 순서대로 순회하면서 반복하는 반복자를 생성하는 함수이다.
미리 생성된 일정 수의 thread가 테스크를 기다리는 공간이다.
thread들은 process가 시작되는 시점에 생성되어 pool에 담겨진다.
(웹 서버를 예로) 서버가 요청을 받으면 사용가능한 thread를 pool에서 꺼내와 해당 thread에 요청을 할당하고, 작업이 끝나면 다시 pool에 돌려 놓는다. 이용가능한 thread가 없을 경우 다른 thread의 작업이 끝나 pool에 돌아올 때까지 기다린다.
요청이 올 때마다 thread를 생성하는 것보다 시간 비용을 줄일 수 있다.
thread의 총량을 관리할 수 있다.
테스크의 생성과 실행을 분리할 수 있다.