Java线程池必知必会知识点总结

yizhihongxing

Java线程池必知必会知识点总结

在并发编程中,线程池是一种重要的资源管理方式。线程池可以管理和执行多个线程,从而提高程序的性能和效率,同时还能避免线程创建和销毁的开销。

本文将介绍Java线程池的相关知识点,包括线程池的基本概念、实现原理、使用方法和注意事项。

线程池的基本概念

Java中的线程池主要有两种实现方式:FixedThreadPool和CachedThreadPool。

  • FixedThreadPool指定池大小,当需要执行任务时如果池中没有可用线程,则任务会被阻塞,直到有足够的可用线程执行。
  • CachedThreadPool不指定池大小,线程池会尽量使用空闲线程执行任务,如果没有空闲线程就会创建新线程执行任务,如果线程空闲时间超过指定时间(默认60秒)则被回收。

线程池的核心参数包括以下几个:

  • corePoolSize: 线程池核心线程数,即线程池中最少的线程数。
  • maximumPoolSize: 线程池最大线程数,即线程池中最多的线程数。
  • keepAliveTime: 空闲线程存活时间,即超过corePoolSize的线程的最大空闲时间,单位为毫秒。
  • TimeUnit: keepAliveTime的时间单位,可以是秒、分钟、小时等。
  • BlockingQueue: 等待队列,用于存放尚未执行的任务。

线程池的实现原理

Java线程池的实现原理主要是通过ThreadPoolExecutor类实现的。

ThreadPoolExecutor是线程池的核心类,它负责管理线程的创建、销毁、调度以及任务的执行。ThreadPoolExecutor的初始化需要传入上述核心参数,以及一个RejectedExecutionHandler对象。

RejectedExecutionHandler是一个回调处理接口,当线程池无法执行新的任务时,会调用该接口的rejectedExecution方法。Java中提供了一些实现了该接口的类,比如AbortPolicy、CallerRunsPolicy、DiscardPolicy和DiscardOldestPolicy。如果不传入RejectedExecutionHandler对象,则使用默认的AbortPolicy。

线程池的使用方法

使用Java线程池主要包括以下步骤:

  1. 创建一个ThreadPoolExecutor对象,指定核心参数和RejectedExecutionHandler对象。
  2. 使用ThreadPoolExecutor的submit方法提交任务,submit()方法会返回Future对象,可以通过该对象判断任务是否执行完成。
ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 5, 60L, TimeUnit.SECONDS,
        new LinkedBlockingQueue<Runnable>());
for (int i = 0; i < 10; i++) {
    executor.submit(new Runnable() {
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() + " is running");
        }
    });
}

上述代码创建了一个核心线程数为2,最大线程数为5的线程池,并往线程池中提交了10个任务。因为等待队列使用的是LinkedBlockingQueue,所以当线程池中有空闲线程时,会直接使用空闲线程执行任务。

  1. 关闭线程池。一般情况下,我们不需要手动调用ThreadPoolExecutor的shutdown方法关闭线程池,因为JVM会在程序退出时自动关闭线程池。但是如果需要手动关闭线程池,应该先调用ThreadPoolExecutor的shutdown方法,此时线程池会拒绝接受新任务,并尝试完成已经提交的任务。如果还有未完成的任务,这些任务会被等待完成,如果等待超时,则会强制中断还在运行的任务。
executor.shutdown();

线程池的注意事项

  • 最大线程数的设置需要考虑当前环境的硬件资源,比如CPU核数、内存大小等。
  • 使用线程池不能滥用,应该根据具体情况合理使用。
  • 对于执行时间较短的任务,可以使用CachedThreadPool,对于执行时间长的任务,可以使用FixedThreadPool。
  • 记得关闭线程池。

示例1:FixedThreadPool

ExecutorService executorService = Executors.newFixedThreadPool(5);
for (int i = 0; i < 10; i++) {
    executorService.submit(new Runnable() {
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() + " is running");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    });
}
executorService.shutdown();

上面的代码创建了一个核心线程数为5的线程池,并提交了10个任务。因为线程池的核心线程数只有5,所以只创建了5个线程执行任务,其他任务则等待空闲线程执行。

运行结果如下:

pool-1-thread-1 is running
pool-1-thread-2 is running
pool-1-thread-4 is running
pool-1-thread-3 is running
pool-1-thread-5 is running
pool-1-thread-1 is running
pool-1-thread-2 is running
pool-1-thread-4 is running
pool-1-thread-3 is running
pool-1-thread-5 is running

可以看到,线程池中的5个线程依次执行了10个任务,每个任务执行1秒钟。

示例2:CachedThreadPool

ExecutorService executorService = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
    executorService.submit(new Runnable() {
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() + " is running");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    });
}
executorService.shutdown();

上面的代码创建了一个没有核心线程数限制的线程池,并提交了10个任务。因为线程池没有限制最大线程数,所以会根据任务的数量和执行时间来自动创建和回收线程。

运行结果如下:

pool-1-thread-2 is running
pool-1-thread-1 is running
pool-1-thread-3 is running
pool-1-thread-4 is running
pool-1-thread-5 is running
pool-1-thread-6 is running
pool-1-thread-7 is running
pool-1-thread-8 is running
pool-1-thread-10 is running
pool-1-thread-9 is running

可以看到,线程池中创建了10个线程,并且线程的创建和回收是自动的。每个任务执行1秒钟。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java线程池必知必会知识点总结 - Python技术站

(0)
上一篇 2023年5月20日
下一篇 2023年5月20日

相关文章

  • Java十道入门易踩坑题分析前篇

    以下是“Java十道入门易踩坑题分析前篇”的完整攻略: 一、问题背景 该篇攻略主要是针对初学者容易踩坑的Java入门题目进行分析和讲解,旨在帮助初学者更好地理解Java编程的基础知识和基本语法。在该篇攻略中,将讲解含有多条示例。 二、题目分析 题目一:计算机系统与数据科学学院有n个学生,每个学生有m个成绩,求每个学生的平均成绩并输出。输入格式:第一行输入数据…

    Java 2023年5月19日
    00
  • Java基础之创建虚拟机对象的过程详细总结

    首先我们需要了解Java创建虚拟机对象的过程。当使用new关键字创建一个对象的时候,Java虚拟机需要经过以下几个步骤: 1.检查是否已经加载该类,如果没有,则加载它。 2.检查该类是否继承自其它类或实现了接口,如果有,则需要先加载这些父类和接口。 3.为对象分配内存空间。 4.对内存空间进行必要的初始化。 5.调用对象的构造方法对对象进行初始化。 下面是两…

    Java 2023年5月26日
    00
  • Java中Map与JSON数据之间的互相转化

    Java中Map与JSON数据之间的转化是Java开发中常见的操作,特别是在进行前后端数据交互的过程中。下面是Java中Map与JSON数据之间互相转化的完整攻略。 1. Map转JSON 将Map转化为JSON格式的数据可以使用Gson、Jackson等第三方库进行实现。 1.1 Gson实现 Gson是Google提供的一个Java中的JSON处理库,可…

    Java 2023年5月26日
    00
  • Springboot使用influxDB时序数据库的实现

    接下来我将详细讲解“Springboot使用influxDB时序数据库的实现”的完整攻略。首先需要明确的是,influxDB是一个高性能的时序数据库,专门用于处理时间序列数据。而Springboot是一个基于Spring框架的应用程序快速开发框架。 引入influxDB依赖 在Springboot项目的pom.xml文件中,添加以下依赖: <depen…

    Java 2023年5月20日
    00
  • Java多线程Semaphore工具的使用详解

    Java多线程Semaphore工具的使用详解 Semaphore是Java中的一个线程同步工具,可以用于控制线程的并发数,也可以用于多个线程之间的互斥访问。 Semaphore的特性 Semaphore主要有以下特性: 控制并发数:Semaphore可以限制并发线程数,保证同时运行的线程数量不超过Semaphore的指定值。 互斥访问:Semaphore可…

    Java 2023年5月19日
    00
  • 带你入门java雪花算法原理

    带你入门java雪花算法原理 概述 雪花算法(Snowflake)是 Twitter 开源的分布式 id 生成算法,以其独特的 id 生成方式,广泛用于分布式系统中唯一 id 的生成,保证了分布式系统中数据的唯一性。 原理 雪花算法生成的 id 是一个 64 位的 long 型整数,其中: 1 bit:表示不可用,Java long 类型的高位是符号位,正数…

    Java 2023年5月19日
    00
  • Java 超详细讲解核心类Spring JdbcTemplate

    Java 超详细讲解核心类Spring JdbcTemplate 简介 Spring JdbcTemplate 是 Spring Framework 提供的一个核心类,用于操作关系型数据库。使用 JdbcTemplate 可以避免手动创建和释放数据库连接的繁琐过程,同时也可以更加方便地执行 SQL 查询和操作数据库。 配置 在使用 Spring JdbcTe…

    Java 2023年5月19日
    00
  • 用Java实现FTP服务器解决方案

    用Java实现FTP服务器解决方案 介绍 FTP(File Transfer Protocol)是一种用于在服务器和计算机之间传输文件的协议。Java可以通过一些库和框架来实现FTP服务器的功能,使得开发者可以基于Java快速构建FTP服务器,以满足业务需求。 准备工作 在实现FTP服务器之前,需要进行以下准备工作: JDK环境的安装和配置 FTP服务器框架…

    Java 2023年6月15日
    00
合作推广
合作推广
分享本页
返回顶部