A API do Java trabalha em formato de pilhas, digamos assim. Veja o código abaixo:
int i = 0;
System.out.print("Oi");
calcularAlgumaCoisa();
System.out.print("Oi");
public void calcularAlgumaCoisa(){
calcularOutraCoisa();
}
A ordem de execução do Java é sequencial, logo o código acima vai criar e inicializar a variável i, depois vai imprimir na tela, em seguida executar o método calcularAlgumaCoisa. Neste ponto, a lógica de processamento é direcionada para o método em questão e a pilha de baixo é pausada. No método calcularAlgumaCoisa tem uma chamada para o método calcularOutraCoisa, e então o processamento é direcionado para ele. No término da execução do método calcularOutraCoisa, o método calcularAlgumaCoisa retoma o processamento e passa para a próxima instrução. No término dele, o fluxo retorna para a pilha principal e segue para a impressão em tela novamente, finalizando o processo de execução principal, por exemplo.
Veja que é um ciclo bem definido com início e fim, onde cada tarefa é processada, podendo desencadear o processamento de novas subtarefas. Por ter este ciclo bem definido, é possível capturar um System.currentTimeMillis() no início e outro no fim. A diferença entre eles resulta no tempo de processamento da tarefa.
Pensa num conceito de cascata, onde a tarefa seguinte é executada somente no término da anterior.