文章目录

  • 一、测试线程开销
    • 1、正常测试
    • 2、不创建线程
    • 3、只创建不启动线程
    • 4、只启动不等待执行完成
  • 二、分析测试结果
    • 1、启动线程分析
    • 2、用户线程与内核线程
    • 3、轻量级进程
    • 4、验证 Java 线程类型

一、测试线程开销


线程池是线程的缓存 , 在 Java 高并发场景中 , 所有的异步操作 , 都可以使用线程池 ;

使用线程池时 , 不建议用在 " 执行耗时较长的操作 " 的业务场景中 ;

线程池机制 最重要的功能就是 复用线程 ; 线程的创建 , 销毁 , 都是要消耗资源的 , 如果频繁创建销毁线程 , 会消耗很多资源 ;

1、正常测试

下面开始测试一下线程创建的开销 :

在主线程中 , 启动 101010 万个线程 , 每个线程中累加 count 变量 ;

public class Main {/*** 线程中对该值进行累加操作*/private static int count = 0;public static void main(String[] args) throws InterruptedException {// 记录程序开始执行时间long startTime = System.currentTimeMillis();// 创建 10 万个线程, 开启线程后, 向集合中添加一个元素for (int i = 0; i < 100000; i ++) {Thread thread = new Thread(new Runnable() {@Overridepublic void run() {count ++;}});// 启动线程thread.start();// 等待线程执行完成thread.join();}// 记录程序执行结束时间long endTime = System.currentTimeMillis();// 打印消耗的时间System.out.println("耗时 : " + ( endTime - startTime ) + " ms , 最终 count = " + count);}
}

执行结果 : 101010 万个线程执行完毕消耗 10.99210.99210.992 秒 ;

2、不创建线程

注释掉线程相关代码 :

public class Main {/*** 线程中对该值进行累加操作*/private static int count = 0;public static void main(String[] args) throws InterruptedException {// 记录程序开始执行时间long startTime = System.currentTimeMillis();// 创建 10 万个线程, 开启线程后, 向集合中添加一个元素for (int i = 0; i < 100000; i ++) {/*Thread thread = new Thread(new Runnable() {@Overridepublic void run() {count ++;}});// 启动线程thread.start();// 等待线程执行完成thread.join();*/}// 记录程序执行结束时间long endTime = System.currentTimeMillis();// 打印消耗的时间System.out.println("耗时 : " + ( endTime - startTime ) + " ms , 最终 count = " + count);}
}

执行结果 : 111 ms 执行完毕 ; 说明耗时操作是在 for 循环中 ;

3、只创建不启动线程

注释掉线程启动代码 :

public class Main {/*** 线程中对该值进行累加操作*/private static int count = 0;public static void main(String[] args) throws InterruptedException {// 记录程序开始执行时间long startTime = System.currentTimeMillis();// 创建 10 万个线程, 开启线程后, 向集合中添加一个元素for (int i = 0; i < 100000; i ++) {Thread thread = new Thread(new Runnable() {@Overridepublic void run() {count ++;}});/*// 启动线程thread.start();// 等待线程执行完成thread.join();*/}// 记录程序执行结束时间long endTime = System.currentTimeMillis();// 打印消耗的时间System.out.println("耗时 : " + ( endTime - startTime ) + " ms , 最终 count = " + count);}
}

执行结果 : 耗时 797979 ms , 也很快 , 大部分时间都在 启动 与 等待线程执行完毕消耗 ;

4、只启动不等待执行完成

注释掉等待线程执行完成代码 :

public class Main {/*** 线程中对该值进行累加操作*/private static int count = 0;public static void main(String[] args) throws InterruptedException {// 记录程序开始执行时间long startTime = System.currentTimeMillis();// 创建 10 万个线程, 开启线程后, 向集合中添加一个元素for (int i = 0; i < 100000; i ++) {Thread thread = new Thread(new Runnable() {@Overridepublic void run() {count ++;}});// 启动线程thread.start();// 等待线程执行完成//thread.join();}// 记录程序执行结束时间long endTime = System.currentTimeMillis();// 打印消耗的时间System.out.println("耗时 : " + ( endTime - startTime ) + " ms , 最终 count = " + count);}
}

执行结果 : 耗时 3.8663.8663.866 秒 ;

二、分析测试结果


1、启动线程分析

在上述测试中 , 如果只是创建 101010 万个 Thread 对象 , 这些在 Java 中就是普通的对象 ;

但是如果调用了 Thread 对象的 start() 方法 , 就要涉及到系统的线程切换 , 这个操作非常耗时 ;

操作系统的空间 , 分为 用户空间 和 内核空间 ;

用户空间中 , 有多个进程 , 每个进程有多个线程 , 每个进程都有一个 线程表 , 用于保存该进程中的线程 ;

JVM 创建的线程是 内核线程 ;

执行 main 函数时 , 处于 用户态 , 一旦调用了 start() 方法启动了线程 , 此时就进入了 内核态 , 该状态切换消耗巨大 ;

2、用户线程与内核线程

系统的线程分为 用户线程 和 内核线程 ;

用户线程 : 用户线程是 用户程序实现的线程 , 并负责管理线程的 创建 , 执行 , 调度 , 同步 ;

  • 线程阻塞时 , 进程也会阻塞 ;

( Java 没有用到用户线程 )

内核线程 : 内核线程是 由内核管理的线程 , 其内部保存了线程的状态信息 , 上下文信息 , 如果频繁的切换线程 , 需要反复处理状态信息 , 上下文信息 , 会浪费很多资源 ;

  • 线程阻塞时 , 进程不会阻塞 ;
  • 内核线程效率比用户线程低 , 比进程高 ;

3、轻量级进程

轻量级进程 : 在我们写的程序中 , 虽然使用了内核线程 , 但 没有直接使用 , 而是 通过内核线程的高级接口使用内核线程 , 这个高级接口就是 " 轻量级进程 " , Java 程序中的 Thread 就是轻量级进程 , 每个 轻量级进程 都对应一个 内核线程 ;

4、验证 Java 线程类型

在任务管理器中可以查看线程数 :

执行下面的程序 : 创建了 100001000010000 个线程

public class Test {public static void main(String[] args) {for (int i = 0; i < 10000; i ++){new Thread(()->{try {Thread.sleep(10000);} catch (InterruptedException e) {e.printStackTrace();}}).start();}}
}

创建 100001000010000 线程后 , 发现线程数增加了 100001000010000 ;

由此可见 , Java 虚拟机创建的线程是内核线程 ;

Java 虚拟机创建线程 , 依赖于系统内核 , 内核空间的内核线程 与 用户空间的 Java 线程 是一一对应的关系 ;

【Java 并发编程】线程池机制 ( 测试线程开销 | 启动线程分析 | 用户态 | 内核态 | 用户线程 | 内核线程 | 轻量级进程 )相关推荐

  1. Java并发编程之锁机制之LockSupport工具

    关于文章涉及到的jdk源码,这里把最新的jdk源码分享给大家----->jdk源码 前言 在上篇文章<Java并发编程之锁机制之AQS(AbstractQueuedSynchronizer ...

  2. 【Java 并发编程】线程池机制 ( ThreadPoolExecutor 线程池构造参数分析 | 核心线程数 | 最大线程数 | 非核心线程存活时间 | 任务阻塞队列 )

    文章目录 前言 一.ThreadPoolExecutor 构造参数 二.newCachedThreadPool 参数分析 三.newFixedThreadPool 参数分析 四.newSingleTh ...

  3. 【Java 并发编程】线程池机制 ( 线程池示例 | newCachedThreadPool | newFixedThreadPool | newSingleThreadExecutor )

    文章目录 前言 一.线程池示例 二.newCachedThreadPool 线程池示例 三.newFixedThreadPool 线程池示例 三.newSingleThreadExecutor 线程池 ...

  4. 高性能dhcp服务器,基于线程池机制的高性能DHCP服务器研究与实现

    摘要: 随着互联网的蓬勃发展,IP地址资源越来越紧张.DHCP服务是在现有IPv4协议基础上解决IP地址资源短缺问题的有效途径. 目前,多数DHCP服务器是单线程运行,串行处理客户请求的.其应用于大型 ...

  5. dhcp计算机毕业论文,基于线程池机制的高性能DHCP服务器研究与实现-计算机科学与技术专业毕业论文.docx...

    文档介绍: 西北丁业大学硕士学位论文 摘要摘 要随着互联网的蓬勃发展,IP地址资源越来越紧张.DHCP服务是在现有IPv4协议基础上解决IP地址资源短缺问题的有效途径.目前,多数DHCP服务器是单线程 ...

  6. Java并发编程—AQS原理分析

    目录 一.AQS原理简述 二.自定义独占锁及共享锁 三.锁的可重入性 四.锁的公平性 五.惊群效应 AQS全称AbstractQueuedSynchronizer,它是实现 JCU包中几乎所有的锁.多 ...

  7. Java并发编程:Thread类的使用

    为什么80%的码农都做不了架构师?>>>    Java并发编程:Thread类的使用 在前面2篇文章分别讲到了线程和进程的由来.以及如何在Java中怎么创建线程和进程.今天我们来学 ...

  8. 【Java 并发编程】CountDownLatch 使用场景示例

    文章目录 I CountDownLatch 使用场景举例 II CountDownLatch 简单线程阻塞示例 III CountDownLatch 多个线程联合阻塞示例 I CountDownLat ...

  9. 【Java 并发编程】线程池机制 ( 线程池执行任务细节分析 | 线程池执行 execute 源码分析 | 先创建核心线程 | 再放入阻塞队列 | 最后创建非核心线程 )

    文章目录 一.线程池执行任务细节分析 二.线程池执行 execute 源码分析 一.线程池执行任务细节分析 线程池执行细节分析 : 核心线程数 101010 , 最大小成熟 202020 , 非核心线 ...

最新文章

  1. 根据Word表格自动生成SQL数据库脚本的VBScript代码
  2. 彻底弄懂C语言数组名
  3. ExtJs FormPanel布局
  4. python如何连接自己电脑服务器_Python远程连接windows服务器并上传数据
  5. 说说Java中原子性,可见性与指令重排序的理解
  6. UIKeyboard键盘相关知识点
  7. 经纬度坐标转换成px_经纬度坐标转像素坐标
  8. hibernate文档
  9. 数据结构上机实践第10周项目1 - 二叉树算法验证
  10. android mvp模式例子_[Android] MVP设计模式及实例
  11. setInterval.js
  12. 容器和泛型 容器重点掌握
  13. 阿里巴巴大数据实践:大数据建设方法论OneData
  14. 版本名称SNAPSHOT、alpha、beta、release、GA含义
  15. Vim文件和日历操作
  16. 小强源码分析系列-Spring Boot2-源码分析1---调试环境搭建
  17. 二代测序(Next generation sequencing)介绍
  18. Web前端人员如何提升能力 提高效率有哪些方法
  19. 【dbeaver】发生了错误。请参阅日志文件
  20. gmail通讯录同步

热门文章

  1. 优秀交互设计的 UI 原则
  2. ORz.....-0-
  3. 启动nuxt项目fsevents报错
  4. 【原创】原来你竟然是这样的Chrome?!Firefox笑而不语
  5. Ubuntu18.04 VMtools的安装与卸载
  6. Git详解之五 分布式Git
  7. 动态数据绑定之监听对象变化
  8. [转载] 后台进程符的使用 [文摘]
  9. JavaScript代码规范
  10. Kafka(1)-概述