12

检查此代码

    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 线程应该是用户空间线程,对吧?所以一个被阻塞的线程应该阻塞整个过程......那不是发生的事情。他们发生了什么事?

4

3 回答 3

20

Java 线程是“用户”线程,但在底层,Java 虚拟机使用内核线程并在其内核线程池中的每个内核线程上委派用户线程 CPU 时间。请参阅此问题以获得更好的解释。似乎线程是特定于 JVM 供应商的,我的理解可能不适用于所有 JVM 实现。

于 2013-08-16T16:54:01.820 回答
6

大多数 JVM 使用本机操作系统级线程实现线程,包括基于 OpenJDK 的 Oracle 参考实现。

我想使用“绿色线程”(线程的用户空间模拟)的 JVM 将使用抢占式调度,以便一个线程中的无限循环不会阻塞其他线程,但是在不了解特定实现的情况下,这只是猜测。

于 2013-08-16T16:59:19.807 回答
1

Java 线程肯定是用户线程,但最终它们会在真正执行之前映射到内核级线程。这种映射可能取决于特定的 JVM 实现(或映射模型)。

调度方面,内核线程在操作系统级别由定期中断内核的闹钟调度。IMO,当这种情况发生时,您的 JVM 线程(可能是多个)可能会执行它的代码,或者可能会产生另一个线程(这可能导致操作系统创建另一个内核线程或根据映射模型阻止它),或者可能运行它自己特定的调度算法来决定哪个线程先前被阻塞在同一个锁上,接下来将进行上下文切换等。

于 2018-05-19T22:24:26.193 回答