我正在开发一个播放音乐的应用程序。
在回放期间,通常情况需要在单独的线程上发生,因为它们需要同时发生。例如,一个和弦需要的音符一起被听到,所以每个人都分配了其自己的线程中进行播放(编辑澄清:调用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...
取决于语言的线程模型。用于并行处理的线程通常在操作系统级别处理,因此操作系统可以将它们映射到多个内核。创建和在这些线程之间进行切换非常昂贵。并发线程(交织两个任务,不必同时执行两个任务)可以在语言/ VM级别上实现,并且可以非常“便宜”地进行生产和切换,因此您可以说与10个网络套接字进行通信同时进行,但不一定以这种方式获得更多的CPU吞吐量。