What are the ways to create a thread in Java, and which one should you actually use?
There are three interfaces you can implement, and in practice you should only use one of them.
Runnable has a single method, run(), and it returns nothing and cannot throw a checked exception. You pass it to new Thread(runnable) or submit it to an executor.
Callable has a single method, call(), which returns a value and may throw a checked exception. It is the interface you want whenever the work produces a result, because a thread that just runs cannot hand anything back — the only way to get data out of it is through shared mutable state, which is exactly the kind of bug you are trying to avoid.
Thread is the class itself. Extending it is legal but almost always the wrong choice, because Java has single inheritance and your class then cannot extend anything else. It also mixes up the work with the mechanism: the task and the thread that runs it are different concerns, and a Runnable can be run on any executor you like.
There is a fourth option worth naming for completeness: Thread.ofVirtual() and the virtual thread executors, which are now part of the language. Those change the cost model rather than the interface — you still supply a Runnable or a Callable, but the thread is cheap enough that you can have very many of them.
The advice for interviews is short. Implement Runnable or Callable, never extend Thread, and prefer an ExecutorService over creating threads by hand so that you get pooling, error handling and a clean shutdown for free.