← Apple Interview Insights

Apple·Software Engineer·Technical Phone Screen·Intermediate

Intermediate
Apr 2026

Summary

Apple SWE technical phone screen, one question that went deeper than I expected on Java concurrency basics. Felt okay about it but definitely left some things on the table.

Questions Asked (1)

Q1

What are the differences between Runnable and Callable in Java, and when would you use one over the other?

Technical Trade-offsAPI & Integrations
Author's notes

Started fine, covered the void vs generic return type difference and the checked exception thing.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by defining Runnable and Callable, highlighting their core differences in return values and exception handling. Then explain when to use each, focusing on use cases like fire-and-forget tasks versus tasks that produce results or throw checked exceptions. Finally, mention how they integrate with ExecutorService and other concurrency utilities.

Pro tip: Emphasize that Callable is often used with Future to retrieve results asynchronously, and mention that Runnable can be wrapped into a Callable using Executors.callable() if needed. This shows deep familiarity with the java.util.concurrent API.

1. Define Runnable and Callable

State that Runnable is a functional interface with a single run() method that returns void and cannot throw checked exceptions. Callable is also a functional interface with a call() method that returns a value and can throw checked exceptions.

2. Compare key differences

Highlight the differences: return type (void vs. generic V), exception handling (unchecked vs. checked), and the method name (run vs. call). Mention that Callable was introduced in Java 5 as part of the concurrency utilities.

3. Explain usage scenarios

Describe when to use Runnable: for tasks that don't need to return a result or throw checked exceptions, such as event handling or simple background tasks. Use Callable when you need a result, need to propagate checked exceptions, or want to use Future for asynchronous computation.

4. Discuss integration with ExecutorService

Explain that both can be submitted to an ExecutorService, but Callable submissions return a Future that can be used to retrieve the result or handle exceptions. Runnable submissions return a Future<?> that only allows checking completion.

5. Mention conversion and best practices

Note that Runnable can be converted to Callable using Executors.callable(), and that Callable is preferred for tasks that produce results or need exception handling. Also mention that both are used in parallel streams and CompletableFuture.

Key Points to Mention

  • Runnable's run() returns void; Callable's call() returns a value of type V.
  • Runnable cannot throw checked exceptions; Callable can throw checked exceptions.
  • Callable is typically used with Future to obtain results asynchronously.
  • Runnable is suitable for fire-and-forget tasks; Callable for tasks that produce results.
  • Both are functional interfaces and can be used with lambdas.
  • Executors.callable() can adapt a Runnable to a Callable.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.