Несколько потоков - это отдельные «цепочки» команд внутри одного процесса. С точки зрения ЦП потоки более или менее похожи на процессы. Каждый поток имеет свой набор регистров и свой стек.
Причина, по которой вы можете иметь больше потоков, чем процессоров, заключается в том, что большинству потоков не требуется процессор все время. Поток может ожидать ввода пользователя, загрузки чего-либо из Интернета или записи на диск. Пока он это делает, ему не нужен процессор, поэтому процессор может свободно выполнять другие потоки.
В вашем примере каждая вкладка Firefox может даже иметь несколько потоков. Или они могут поделиться некоторыми темами. Вам нужен один для загрузки, один для рендеринга, один для цикла сообщений (пользовательский ввод) и, возможно, один для запуска Javascript. Вы не можете легко объединить их, потому что во время загрузки вам все равно нужно реагировать на ввод пользователя. Тем не менее, поток загрузки находится в спящем режиме большую часть времени, и даже когда он загружается, ему требуется процессор только изредка, а поток цикла сообщений активируется только при нажатии кнопки.
Если вы зайдете в диспетчер задач, то увидите, что, несмотря на все эти потоки, загрузка вашего процессора все еще довольно низка.
Конечно, если все ваши потоки выполняют какие-то сложные задачи, вам не следует создавать их слишком много, поскольку вы не получаете никакого выигрыша в производительности (хотя могут быть архитектурные преимущества!).
Однако, если они в основном связаны с вводом / выводом, создайте столько потоков, сколько требует ваша архитектура. Трудно дать совет, не зная вашей конкретной задачи.