在Java中,我知道默认的线程优先级是5。 我有一个课程,它基本上睡了n秒,同时做其他的东西。 如果我以随机顺序创建20个线程,每个线程都以该类作为目标,其中n为10或20秒,那么所有10秒的线程首先完成,然后20秒完成。
我认为会发生的事情是,由于我运行的是双核处理器,因此实际上只能同时运行2个线程。因此,调度程序将任意选择2个线程,因为它们都具有相同的优先级,并首先运行它们,这意味着有时20秒的线程必须在10秒之前运行,依此类推。依此类推。
答案 0 :(得分:6)
我认为这是因为线程的量子比计划时的10或20秒的运行时间要小得多。即使20秒的线程首先进入运行队列,它也不会一次完全运行。在时间片用完后,线程调度程序会将其返回到等待队列,这可能是相对较短的时间。
有关线程调度算法的一篇非常好的文章,请参阅here。基本的总结是每个线程将运行一段时间(可能是毫秒级),然后它将被换出另一个线程。此线程交换将继续,直到所有线程都完成。
此外,Wikipedia entry的日程安排非常好。虽然其中一些特别指的是进程调度,但现代操作系统通常以相同的方式处理线程。
答案 1 :(得分:3)
线程在休眠时实际上并没有消耗CPU时间。 Thread.sleep(10000)
只是意味着“现在可以执行其他线程的执行,并且仅在至少10秒钟后再次重新考虑此线程以进行调度”。所以所有线程都可以同时睡眠。
答案 2 :(得分:2)
所有线程都“同时”运行。这就是线程的工作方式。两个线程同时运行,但随后被关闭,以便其他线程可以运行(等等......)。线程在完成之前不会保留处理器。
因此,10秒线程首先完成是有意义的。
答案 3 :(得分:0)
线程优先级只是向JVM指示您的线程应该优先考虑的内容。没有硬保证,并且由于JVM只是操作系统上的一个进程,外部进程可能会影响可用的CPU周期数量。 JVM以及进程实际运行的方式。
一般情况下,您应该考虑查看Executors,它允许您将大量Runnables / Callables填充到工作中的桶中。工作的确切方式取决于您为此目的选择的执行者。另外,对于长时间运行的代码块,请使用Thread.yield(),因为它允许JVM重新安排。
答案 4 :(得分:0)
根据您的使用案例,您可以通过将ThreadPoolExecutor与PriorityQueue相结合来接近您期望的行为。
Executor可以限制您同时运行2个任务 - 因此睡眠的任务将阻止其他任务。
可以确保PriorityQueue确保当一个线程空闲时,剩余的最高优先级任务是被选中接下来运行的任务。
现在,如果启动的第一个任务是低优先级,启动时可能会有点小问题,因为这个方案不会抢先运行任务。这可能对您有用,也可能无关紧要。
请注意,针对Exectutors的Java 5 API使得这种安排几乎不可能开始工作。你真的需要Java 6的更改,除非你喜欢在反射API中弄脏你的手......
答案 5 :(得分:-1)
完全由jvm决定首先运行tun的线程。即使首先运行20s线程并进入睡眠状态,也可以启动10s线程。因此,如果实际计算很小,例如几毫秒,所有10s线程将首先完成。