같은 Runnable의 동기 호출과 비동기 시작

예외가 전달되는 stack과 완료 회수 방법이 달라진다.

task.run

현재 caller가 수행하고 caller catch가 예외를 받는다

synchronous

thread.start

worker handler가 uncaught exception을 받고 join은 종료만 기다린다

asynchronous
결과가 필요할 때Future처럼 값과 실패를 회수하는 abstraction을 선택한다

핵심: join은 worker exception을 호출자에게 자동으로 다시 던지지 않는다.