一文带你深入剖析Java线程池的前世今生

 更新时间:2022年10月18日 08:14:26   作者:一无是处的研究僧  
这篇文章主要带大家介绍了深入剖析一下Java线程池的前世今生,了解线程池的原理以及为什么需要线程池。文中的示例代码讲解详细,需要的可以参考一下

由线程到线程池

线程在做什么

灵魂拷问:写了那么多代码,你能够用一句话简练描述线程在干啥吗?

public class Demo01 {

  public static void main(String[] args) {
    var thread = new Thread(() -> {
      System.out.println("Hello world from a Java thread");
    });
    thread.start();
  }
}

我们上面的这个用线程输出字符串的代码来进行说明。我们知道上面的Java代码启动了一个线程,然后执行lambda函数,在以前没有lambda表达式的时候我们可以使用匿名内部类实现,向下面这样。

public class Demo01 {

  public static void main(String[] args) {
    var thread = new Thread(new Runnable() {
      @Override
      public void run() {
        System.out.println("Hello world from a Java thread");
      }
    });
    thread.start();
  }
}

但是本质上Java编译器在编译的时候都认为传递给他的是一个对象,然后执行对象的run方法。刚刚我们使用的Thread的构造函数如下:

    public Thread(Runnable target) {
        this(null, target, "Thread-" + nextThreadNum(), 0);
    }

Thread在拿到这个对象的时候,当我们执行Threadstart方法的时候,会执行到一个native方法start0

当JVM执行到这个方法的时候会调用操作系统给上层提供的API创建一个线程,然后这个线程会去解释执行我们之前给Thread对象传入的对象的run方法字节码,当run方法字节码执行完成之后,这个线程就会退出。

看到这里我们仔细思考一下线程在做一件什么样的事情,JVM给我们创建一个线程好像执行完一个函数(run)的字节码之后就退出了,线程的生命周期就结束了。确实是这样的,JVM给我们提供的线程就是去完成一个函数,然后退出(记住这一点,这一点很重要,为你后面理解线程池的原理有很大的帮助)。事实上JVM在使用操作系统给他提供的线程的时候也是给这个线程传递一个函数地址,然后让这个线程执行完这个函数。只不过JVM给操作系统传递的函数,这个函数的功能就是去解释执行字节码,当解释执行字节码完成之后,这个函数也会退出(被系统回收)。

看到这里可以将线程的功能总结成一句话:执行一个函数,当这个函数执行完成之后,线程就会退出,然后被回收,当然这个函数可以调用其他的函数,可能你会觉得这句话非常简单,但是这句话会我们理解线程池的原理非常有帮助。

为什么需要线程池

上面我们已经谈到了,当我们执行start的方法的时候,最终会走到start0方法,这是一个native方法,JVM在执行这个方法的时候会通过系统底层函数创建一个线程,然后去执行run方法,这里需要注意,创建线程是需要系统资源的,比如说内存,因为操作系统是系统资源的管理者,因此一般需要系统资源的方法都需要操作系统的参与,因此创建线程需要操作系统的帮忙,而一旦需要操作系统介入,执行代码的状态就需要从用户态到内核态转换(内核态能够执行许多用户态不能够执行的指令),当操作系统创建完线程之后有需要返回用户态,我们的代码将继续被执行,整个过程像下面这样。

从上图可以看到我们需要两次的上下文切换,同时还需要执行一些操作系统的函数,这个过程是非常耗时间的,如果在并发非常高的情况,我们频繁的去生成线程然后销毁,这对我们程序的性能影响还是非常大的。因此许许多多聪明的程序员就想能不能不去频繁的创建线程而且也能够完成我们的功能——我们创建线程的目的就是想让我们的程序完成的更加快速,让多个不同的线程同时执行不同的任务。于是线程池就被创造出来了。线程池的结构大致如下所示:

线程池实现原理

在前面我们已经提到了关于线程池和线程比较重要的两个点:

  • 线程就是执行一个函数。
  • 线程池当中的线程可以执行很多函数,但是不会退出。

凭借你朴素的情感,你觉得如何实现上面两个要求。答案就是在一个函数当中进行while循环,然后不断的从任务队列当中获取任务函数,然后进行执行,直到要求停止线程池当中的线程的时候线程再进行退出,整个过程的代码大致如下所示:

  public void run() {
    while (!isStopped) {
      try {
        Runnable task = tasks.take();
        task.run();
      } catch (InterruptedException e) {
        // do nothing
      }
    }
  }

关于线程池要有一部分细节也很重要,比如说我们需要一个并发安全的阻塞队列,如何保证所有线程正常退出等等,我们在下篇文章当中进行实现,而且将仔细分析这里面的细节。

总结

在本篇文章当中主要给大家介绍了线程到线程池的演化过程,主要介绍线程池实现的基本原理,主要解读了线程池背后的基本原理,希望大家有所收获!

以上就是一文带你深入剖析Java线程池的前世今生的详细内容,更多关于Java线程池的资料请关注脚本之家其它相关文章!

相关文章

  • spring在IoC容器中装配Bean详解

    spring在IoC容器中装配Bean详解

    这篇文章主要介绍了spring在IoC容器中装配Bean详解,具有一定借鉴价值,需要的朋友可以参考下
    2017-12-12
  • Java利用多线程模拟银行系统存钱问题

    Java利用多线程模拟银行系统存钱问题

    本文将利用Java多线程模拟银行系统存钱问题:使用两个不同的线程向同一个账户存钱。文中的示例代码讲解详细,感兴趣的可以了解一下
    2022-08-08
  • 详解Java中final的用法

    详解Java中final的用法

    本文主要介绍了Java中final的使用方法,final是java的关键字,本文就详细说明一下它的使用方法,需要的朋友可以参考下
    2015-08-08
  • RabbitMQ消费端ACK NACK及重回队列机制详解

    RabbitMQ消费端ACK NACK及重回队列机制详解

    这篇文章主要为大家介绍了RabbitMQ消费端ACK NACK及重回队列机制详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-12-12
  • SpringBoot如何优雅的处理重复请求

    SpringBoot如何优雅的处理重复请求

    对于一些用户请求,在某些情况下是可能重复发送的,如果是查询类操作并无大碍,但其中有些是涉及写入操作的,一旦重复了,可能会导致很严重的后果,所以本文给大家介绍了SpringBoot优雅的处理重复请求的方法,需要的朋友可以参考下
    2023-12-12
  • SpringBoot自定义注解及AOP的开发和使用详解

    SpringBoot自定义注解及AOP的开发和使用详解

    在公司项目中,如果需要做一些公共的功能,如日志等,最好的方式是使用自定义注解,自定义注解可以实现我们对想要添加日志的方法上添加,这篇文章基于日志功能来讲讲自定义注解应该如何开发和使用,需要的朋友可以参考下
    2023-08-08
  • JAVA新手小白学正则表达式、包装类、自动装箱/自动拆箱以及BigDecimal

    JAVA新手小白学正则表达式、包装类、自动装箱/自动拆箱以及BigDecimal

    这篇文章主要给大家介绍了关于JAVA新手小白学正则表达式、包装类、自动装箱/自动拆箱以及BigDecimal的相关资料,文中通过实例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2022-03-03
  • 零基础搭建boot+MybatisPlus的详细教程

    零基础搭建boot+MybatisPlus的详细教程

    这篇文章主要介绍了零基础搭建boot+MybatisPlus,首先需要创建数据库表和创建boot项目使用mybatisplus操作数据库,本文通过示例代码给大家介绍的非常详细,需要的朋友可以参考下
    2022-03-03
  • Java设计模式之策略模式详解和示例

    Java设计模式之策略模式详解和示例

    这篇文章主要介绍了Java设计模式之策略模式详解和示例,策略模式就是一种行为可能会因为不同的逻辑造成多个算法,比如人吃饭,美国人吃饭用刀叉,中国吃饭用筷子,都是吃饭的行为但是使用的工具(算法)不一样,需要的朋友可以参考下
    2024-01-01
  • Java HashMap在遍历时删除元素的实现

    Java HashMap在遍历时删除元素的实现

    本文主要介绍了Java HashMap在遍历时删除元素的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-12-12

最新评论