• JVM的线程实现机制


    最近我在看<Advanced Programming on UNIX Environment 2nd Edition>(以下简称APUE), 读到线程这一章节。上面讲到OS提供多线程环境,比如创建线程、销毁线程以及线程的同步控制。我突然想到,”JVM的线程管理是不是调用了OS的线程管理呢?“ 针对这个问题,我做了一些研究。这篇文章是这些研究的总结。由于水平有限(我现在还没有能力读懂JVM的源代码),所以无法提供代码例证,如果文章中出现任何问题和纰漏,请不吝指教。

    线程运行方式

    在单处理器的系统中,多线程是按时间片方式运行的;在多处理器(或者多核)的系统中,多个线程可以同时运行。

    ”On a single processor, multithreading generally occurs by time-division multiplexing; the processor switches between different threads. On a multiprocessor (including multi-core system), the threads or tasks will actually run at the same time.

    --http://en.wikipedia.org/wiki/Thread_(computer_science)

    所以从系统的吞吐量方面来说,多线程是非常重要的。而且即使是单处理器(单核的),多线程依然能够提供提升系统吞吐量的好处,比如某个线程执行的任务受到阻塞,其他的线程依然能够继续运行。

    线程模型

    • 内核级别线程

        内核级别线程(Kernel-level threading)是指用户进程通过内核提供API创建的线程。这样用户进程里的线程和内核调度的线程是1:1对应的。这也就最简单的线程管理方法。

    • 用户级别线程

         用户基本线程(User-level threading)是指 用户进程自己实现线程机制。在这种情况下,内核是不知道有多少线程存在的,同时线程上下文切换更快,而且在不支持多线程的操作系统上也能实现多线程。但是,用户级别的线程也带来相当大的坏处,比如不能充分利用多处理器(多核)系统;如果进程中的一个线程执行阻塞的I/O请求,那么整个用户进程都会被阻塞。

    • 混合线程

         混合线程是内核级别线程和用户级别线程的混合体,提供了以上两种模型的优点,但是带来很大的复杂性。

    绿色进程

    首先看绿色进程的定义:

    绿色线程是指有虚拟机调度的线程,而不是通过内核调度的。所以绿色进程是用户级别的进程。

    ”In computer programming, green threads are threads that are scheduled by a virtual machine (VM) instead of natively by the underlying operating system.

    http://en.wikipedia.org/wiki/Green_threads"

    前面也讲过用户级别线程在I/O或者利用多核处理器方面性能不如内核级别的线程。所以,在Java 1.1以后,JVM就从绿色线程机制转为内核级别线程机制。

     

    由于是内核级别的线程机制,所以JVM的线程数量受到内核参数的影响
     
    通常来说,这个参数是运行时的参数,是内核根据进程的栈空间容量计算出来的。
    cat /proc/sys/kernel/thread-max
     
    修改这个参数值
    echo 1000 > /proc/sys/kernel/threads-max
     
    运行这个程序
     
    /*
     * Copyright (c) 2011.  Peter Lawrey
     *
     * "THE BEER-WARE LICENSE" (Revision 128)
     * As long as you retain this notice you can do whatever you want with this stuff.
     * If we meet some day, and you think this stuff is worth it, you can buy me a beer in return
     * There is no warranty.
     */
    
    package com.google.code.java.core.threads;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class MaxThreadsMain {
    
      public static final int BATCH_SIZE = 4000;
    
      public static void main(String... args) throws InterruptedException {
        List<Thread> threads = new ArrayList<Thread>();
        try {
          for (int i = 0; i <= 100 * 1000; i += BATCH_SIZE) {
            long start = System.currentTimeMillis();
            addThread(threads, BATCH_SIZE);
            long end = System.currentTimeMillis();
            Thread.sleep(1000);
            long delay = end - start;
            System.out.printf("%,d threads: Time to create %,d threads was %.3f seconds %n", threads.size(), BATCH_SIZE, delay / 1e3);
          }
        } catch (Throwable e) {
          System.err.printf("After creating %,d threads, ", threads.size());
          e.printStackTrace();
        }
    
      }
    
      private static void addThread(List<Thread> threads, int num) {
        for (int i = 0; i < num; i++) {
          Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
              try {
                while (!Thread.interrupted()) {
                  Thread.sleep(1000);
                }
              } catch (InterruptedException ignored) {
                //
              }
            }
          });
          t.setDaemon(true);
          t.setPriority(Thread.MIN_PRIORITY);
          threads.add(t);
          t.start();
        }
      }
    }

    alex@ubuntu:~/download/core-java-performance-examples-read-only/src/test/java$ java com.google.code.java.core.threads.MaxThreadsMain 4,000 threads: Time to create 4,000 threads was 1.923 seconds 8,000 threads: Time to create 4,000 threads was 4.465seconds
    echo 1000 > /proc/sys/kernel/threads-max
    alex@ubuntu:~/download/core-java-performance-examples-read-only/src/test/java$ java com.google.code.java.core.threads.MaxThreadsMain
    After creating 604 threads, java.lang.OutOfMemoryError: unable to create new native thread at java.lang.Thread.start0(Native Method) at java.lang.Thread.start(Thread.java:657) at com.google.code.java.core.threads.MaxThreadsMain.addThread(MaxThreadsMain.java:54) at com.google.code.java.core.threads.MaxThreadsMain.main(MaxThreadsMain.java:24)

     可以看出,在没有设定线程最大数1000之前, 以上Java程序可以创建到8000个线程(我中途中断了)。然后,我重新启动机器,执行 echo 1000 > /proc/sys/kernel/threads-max

    然后运行Java程序,出现了创建进程错误的提示。(但是,我想提示信息不正确,应该是线程数超过最大线程数才准确。)

  • 相关阅读:
    ABP 菜单 修改
    C# 过滤器
    RabbitMQ框架构建系列(三)——Net实现RabbitMQ之Producer
    RabbitMQ系列(二)RabbitMQ基础介绍
    RabbitMQ系列(一)AMPQ协议
    MVC 解读WebConfig
    MVC过滤器特性
    asp.net中使用JQueryEasyUI
    asp.net请求到响应的整个过程
    Redis的下载安装部署(Windows)
  • 原文地址:https://www.cnblogs.com/cando/p/2631780.html
Copyright © 2020-2023  润新知