В Java вы можете иметь столько потоков, сколько захотите, и вы не ограничены тем, сколько у вас процессорных ядер. Т.е. даже если бы у вас был только один процессор с одним ядром, вы все равно могли бы написать многопоточное приложение.
JVM выполнит переключение контекста - некоторое время он будет выполнять поток 1, затем поток 2 в течение некоторого времени, затем, возможно, снова поток 1 и так далее, переключаясь между потоками. Эти переключения между потоками могут происходить всего через несколько миллисекунд, поэтому это может создать иллюзию параллельной работы потоков.
В некоторых приложениях быстрее использовать один поток - потому что этот процесс переключение контекста просто увеличивает расходы.
Я действительно написал небольшое многопоточное приложение на днях. В нем было около 30 потоков, и это был случай, когда многопоточность делала приложение более эффективным.
У меня было около 30 URL-адресов, по которым мне нужно было нажать и извлечь некоторые данные. Если бы я делал это в одном потоке, каждый раз, когда я делал запрос и ждал ответа, было бы время ожидания (таким образом, блокируя приложение). При многопоточности другие потоки смогут работать, пока продолжается это ожидание.
Надеюсь, это имеет смысл. Для получения дополнительной информации стоит прочитать о Java Переключение контекста.
Это хороший источник информации о топи c: https://docs.oracle.com/javase/tutorial/essential/concurrency/index.html