检查此代码
Thread t1 = new Thread(new Runnable() {
@Override
public void run()
{
try
{
System.out.println("STARTING SERVER...");
ServerSocket s = new ServerSocket(2544);
System.out.println("SERVER BLOCKED ON ACCEPT");
Socket ss = s.accept();
System.out.println("SERVER NOT BLOCKED ANYMORE");
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
});
t1.start();
Thread t2 = new Thread(new Runnable() {
@Override
public void run()
{
try
{
while(true)
{
Thread.sleep(1000);
System.out.println("Hello");
}
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
});
t2.start();
输出:
STARTING SERVER...
SERVER BLOCKED ON ACCEPT
Hello
Hello
Hello
Hello
Hello
Hello
Hello
...
Java线程应该是用户空间线程,对吗?所以一个被阻止的线程应该阻止整个过程...那不是发生了什么。他们发生了什么事?
答案 0 :(得分:15)
Java线程是“用户”线程,但在幕后,Java虚拟机使用内核线程并在其内核线程池中的每个内核线程上委派用户线程CPU时间。有关更好的说明,请参阅this question。似乎线程是特定于JVM供应商的,我的理解可能不适用于所有JVM实现。
答案 1 :(得分:6)
大多数JVM使用本机OS级别线程实现线程,包括基于OpenJDK的Oracle参考实现。
我认为使用'绿色线程'(线程的用户空间模拟)的JVM将使用抢占式调度,以便一个线程中的无限循环不会阻塞其他线程,但是在不了解特定实现的情况下这只是猜测。
答案 2 :(得分:0)
Java线程确实是用户线程,但最终它们在被真实执行之前被映射到内核级线程。此映射可能取决于特定的JVM实现(或the mapping model)。
调度方面,内核线程在os级别由一个闹钟调度,该闹钟定期中断内核。 IMO,当发生这种情况时,你的JVM线程(可能是多个)可能会执行它的代码,或者可能产生另一个线程(这可能导致os创建另一个内核线程或根据映射模型阻塞它),或者可以运行它自己的特定调度算法来决定先前在同一个锁上阻塞的线程将在下一个上下文切换等。