Я работаю над приложением, которое играет музыку.
Во время воспроизведения часто вещи должны происходить в отдельных потоках, потому что они должны происходить одновременно. Например, ноты аккорда должны быть услышаны вместе, поэтому каждой из них назначается собственный поток для воспроизведения. (Изменить, чтобы уточнить: вызов note.play()
останавливает поток, пока не закончится воспроизведение ноты, и поэтому мне нужно три отдельные темы для прослушивания трех нот одновременно.)
Такое поведение создает много потоков во время воспроизведения музыкального произведения.
Например, рассмотрим музыкальное произведение с короткой мелодией и короткой сопровождающей аккордной прогрессией. Вся мелодия может быть воспроизведена в одном потоке, но для исполнения требуется три потока, поскольку каждый из ее аккордов содержит три ноты.
Таким образом, псевдокод для воспроизведения последовательности выглядит следующим образом:
void playProgression(Progression prog){
for(Chord chord : prog)
for(Note note : chord)
runOnNewThread( func(){ note.play(); } );
}
Таким образом, предполагая, что у прогрессии есть 4 аккорда, и мы играем это дважды, чем мы открываем 3 notes * 4 chords * 2 times
= 24 потока. И это только для того, чтобы играть в нее один раз.
На самом деле, это прекрасно работает на практике. Я не замечаю заметных задержек или ошибок, связанных с этим.
Но я хотел спросить, является ли это правильной практикой или я делаю что-то в корне неправильно. Разумно ли создавать столько потоков каждый раз, когда пользователь нажимает кнопку? Если нет, как я могу сделать это по-другому?
Is it reasonable to create so many threads...
зависит от потоковой модели языка. Потоки, используемые для параллелизма, часто обрабатываются на уровне ОС, поэтому ОС может сопоставлять их с несколькими ядрами. Такие потоки дороги в создании и переключении между ними. Потоки для параллелизма (чередование двух задач, не обязательно выполняющих обе одновременно) могут быть реализованы на уровне языка / виртуальной машины и могут быть чрезвычайно «дешевыми» для создания и переключения между ними, так что вы можете, скажем, общаться с 10 сетевыми сокетами более или менее одновременно, но вы не обязательно получите больше пропускной способности процессора таким образом.