2014-09-24 2 views
8

ThreadPoolExecutor (TPE)에서 콜백은 항상 제출 된 함수와 동일한 스레드에서 실행되도록 보장됩니까?Python ThreadPoolExecutor - 제출 된 func와 동일한 스레드에서 실행되도록 보장되는 콜백입니까?

예를 들어 다음 코드로 테스트했습니다. 여러 번 실행했는데 funccallback은 항상 같은 스레드에서 실행되었습니다. 나는 time.sleep(random.random()) 문, func 즉 적어도 몇 가지 기능을 제거하고 callbacks가 동일한 스레드에 있지 실행했을 때

import concurrent.futures 
import random 
import threading 
import time 

executor = concurrent.futures.ThreadPoolExecutor(max_workers=3) 

def func(x): 
    time.sleep(random.random()) 
    return threading.current_thread().name 

def callback(future): 
    time.sleep(random.random()) 
    x = future.result() 
    cur_thread = threading.current_thread().name 
    if (cur_thread != x): 
     print(cur_thread, x) 

print('main thread: %s' % threading.current_thread()) 
for i in range(10000): 
    future = executor.submit(func, i) 
    future.add_done_callback(callback) 

그러나 실패 할 것 같았다.

내가 작업중인 프로젝트의 경우 콜백은 항상 제출 된 함수와 동일한 스레드에서 실행되어야하므로 TPE에 의해 보장되는지 확인하고 싶습니다. (또한 임의의 수면을 거치지 않은 결과도 수수께끼처럼 보였습니다).

나는 source code for executors을보고 콜백을 실행하기 전에 스레드를 메인 스레드로 전환하는 것처럼 보이지 않습니다. 그러나 단지 확신하고 싶었습니다.

답변

6

ThreadPoolExecutor에 제출 된 Future의 콜백은 작업 자체가 실행 중일 때와 동일한 스레드에서 실행되지만 작업이 완료되기 전에 콜백이 Future에 추가 된 경우에만 실행됩니다. 당신이 Future 완료 후 콜백을 추가하는 경우, 콜백은 당신이 add_done_callback을 붙인 스레드에서 실행됩니다 당신이 볼 수있는 add_done_callback 소스를보고 :.

def add_done_callback(self, fn): 
    """Attaches a callable that will be called when the future finishes. 

    Args: 
     fn: A callable that will be called with this future as its only 
      argument when the future completes or is cancelled. The callable 
      will always be called by a thread in the same process in which 
      it was added. If the future has already completed or been 
      cancelled then the callable will be called immediately. These 
      callables are called in the order that they were added. 
    """ 
    with self._condition: 
     if self._state not in [CANCELLED, CANCELLED_AND_NOTIFIED, FINISHED]: 
      self._done_callbacks.append(fn) 
      return 
    fn(self) 

Future의 상태가 취소 것 나타내거나 경우 완료되면 fn은 현재 실행 스레드에서 바로 호출됩니다. 그렇지 않으면 Future이 완료 될 때 실행될 내부 콜백 목록에 추가됩니다. `ProcessPoolExecutor`에 대한

>>> def func(*args): 
... time.sleep(5) 
... print("func {}".format(threading.current_thread())) 
>>> def cb(a): print("cb {}".format(threading.current_thread())) 
... 
>>> fut = ex.submit(func) 
>>> func <Thread(Thread-1, started daemon 140084551563008)> 
>>> fut = e.add_done_callback(cb) 
cb <_MainThread(MainThread, started 140084622018368)> 
+0

그리고 무엇 : 예를 들어

? 콜백의'get_ident'도 다릅니다. – Winand

관련 문제