【JavaEE】线程池

【JavaEE】线程池

  • 一、引言
      • [1.1 什么是线程池](#1.1 什么是线程池)
      • [1.2 为什么要使用线程池](#1.2 为什么要使用线程池)
  • 二、ThreadPoolExecutor类
      • [2.1 构造方法](#2.1 构造方法)
        • [2.1.1 corePoolSize和maximumPoolSize](#2.1.1 corePoolSize和maximumPoolSize)
        • [2.1.2 KeepAliveTime和unit](#2.1.2 KeepAliveTime和unit)
        • [2.1.3 BlockingQueue<Runnable> workQueue](#2.1.3 BlockingQueue<Runnable> workQueue)
        • [2.1.4 ThreadFactory threadFactory](#2.1.4 ThreadFactory threadFactory)
        • [2.1.5 RejectedExecutionHandler handler](#2.1.5 RejectedExecutionHandler handler)
      • [2.2 模拟拒绝策略](#2.2 模拟拒绝策略)
  • 三、线程池的实例
  • 四、模拟实现线程池

博客结尾有此篇博客的全部代码!!!

一、引言

1.1 什么是线程池

线程池是一种用于管理和复用线程的机制,通过线程池可以有效降低线程创建和销毁的开销,提高系统的响应速度和资源利用率,允许任务等待处理!

1.2 为什么要使用线程池

  1. 线程的创建和销毁相比于进程的创建和销毁是微不足道的,但是大量线程的创建和销毁消耗的资源也是不少的。
  2. 线程的创建是由内核控制的,这个操作是不可控的;而从线程池中取线程用,这个操作是可控的。

操作系统=内核+配套的应用程序。一个操作系统只有一份内核,内核为其他应用程序提供服务。

  • 需要内核配合完成的都是不可控的

Java中的线程池主要通过ThreadPoolExecutor类实现,同时提供了Executors工具类来方便地创建不同类型的线程池。

二、ThreadPoolExecutor类

2.1 构造方法

这里主要讲解第四个构造方法,参数最多,也是面试中最容易问的!

2.1.1 corePoolSize和maximumPoolSize

int corePoolSize(核心线程数):线程池中始终保持的线程数量,即使它们处于空闲状态。

int maximumPoolSize(最大线程数):线程池允许的最大线程数。

2.1.2 KeepAliveTime和unit

long KeepAlive(空闲线程存活时间)。举例:当提交的任务过多,corePoolSize核心线程数不够,线程池就会创建一些新线程来帮忙处理任务,当这些任务处理完,新创建的线程就空闲下来,如果KeepAlive这段时间没有新任务提交,那么这些新创建的线程就会被终止(除corepoolSize核心线程)

TimeUnit unit:代表时间单位(枚举)

2.1.3 BlockingQueue workQueue

BlockingQueue workQueue:表示一个线程安全的队列(用来存储执行的任务),支持在队列为空时阻塞获取操作,以及在队列满时阻塞插入操作。

2.1.4 ThreadFactory threadFactory

ThreadFactory threadFactory:ThreadFactory 是一个接口,用于自定义线程的创建方式。它可以帮助你统一管理线程的名称、优先级、守护线程属性和异常处理。

2.1.5 RejectedExecutionHandler handler

RejectedExecutionHandler handler(拒绝策略):是一个接口,用于处理线程池无法执行任务时的情况。当线程池已满且任务队列也已满时,新提交的任务会被拒绝,Java中有四种默认拒绝策略或者实现RejectedExecutionHandler接口自定义策略。

  1. ThreadPoolExecutor.AbortPolicy(默认策略):任务被拒绝,会抛出 RejectedExecutionException 异常
  2. ThreadPoolExecutor.CallerRunsPolicy:任务被拒绝,会在调用者的线程中运行任务(举例:假设朋友A的电脑坏了,他让我给他帮忙修电脑。但此时我忙着,他就自己动手修电脑)
  3. ThreadPoolExecutor.DiscardOldestPolicy:任务被拒绝,会丢弃队列中最老的任务,然后尝试将新任务加入队列
  4. ThreadPoolExecutor.DiscardPolicy:任务被拒绝,会直接丢弃任务,不抛出异常
  5. 自定义拒绝策略:
java 复制代码
class CustomRejectedExecutionHandler implements RejectedExecutionHandler {
    @Override
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
        
    }
}
  • Runnable r 是被拒绝执行的任务
  • ThreadPoolExecutor executor 是当前的线程池实例。它提供了线程池的运行状态和配置信息

2.2 模拟拒绝策略

java 复制代码
   public static void main(String[] args) {
        //当任务队列满则抛出异常
        RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy();
        ThreadPoolExecutor poolExecutor=new ThreadPoolExecutor(
                2,//核心线程数
                4, // 最大线程数
                60, // 空闲线程存活时间
                TimeUnit.SECONDS, // 时间单位
                new LinkedBlockingQueue<>(2), // 任务队列,容量为 2
                Executors.defaultThreadFactory(), // 默认线程工厂
                handler
        );

        for (int i = 0; i < 100; i++) {
            poolExecutor.submit(()->{
                System.out.println( Thread.currentThread().getName());
            });
        }
    }

执行结果:

三、线程池的实例

ThreadPoolExecutor类实现线程池:允许开发者根据自己需要设定线程池

Executors 工具类:提供了一系列静态方法,用于快速创建不同类型的线程池

图片演示的就是Executors工具类创建线程池!

java 复制代码
  public static void main(String[] args) {
        ExecutorService threadPool = Executors.newFixedThreadPool(2);
        for (int i = 0; i < 10; i++) {
            int id = i;
            threadPool.submit(() -> {
                System.out.println("hello " + id + ", " 
                + Thread.currentThread().getName());
            });
        }
    }

执行结果:

四、模拟实现线程池

java 复制代码
class MyThreadPoolExecutor {
    //先创建一个阻塞队列用来存储任务
    BlockingQueue<Runnable> queue= new LinkedBlockingQueue<Runnable>();
    //创建一个sumbit方法用来提交Runnable
    public void sumbit(Runnable runnable) throws InterruptedException {
        queue.put(runnable);
    }
    //定义一个构造方法来创建线程池中的线程数
    public MyThreadPoolExecutor(int n){
        for (int i = 0; i < n; i++) {
            Thread thread = new Thread(()->{
                    try {
                        while(true){
                        Runnable task=queue.take();//从队列中取出任务
                        task.run();//执行任务
                        }
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }

            });
            thread.start();
        }
    }
}

public class Demo5 {
    public static void main(String[] args) throws InterruptedException {
        MyThreadPoolExecutor executor = new MyThreadPoolExecutor(5);
        for (int i = 0; i < 5; i++) {
            executor.sumbit(()->{
                System.out.println(Thread.currentThread().getName());
            });
        }
    }
}

此篇博客的全部的代码!!!

相关推荐
hqxstudying21 分钟前
Java创建型模式---原型模式
java·开发语言·设计模式·代码规范
Dcs41 分钟前
VSCode等多款主流 IDE 爆出安全漏洞!插件“伪装认证”可执行恶意命令!
java
保持学习ing1 小时前
day1--项目搭建and内容管理模块
java·数据库·后端·docker·虚拟机
京东云开发者1 小时前
Java的SPI机制详解
java
超级小忍1 小时前
服务端向客户端主动推送数据的几种方法(Spring Boot 环境)
java·spring boot·后端
程序无bug1 小时前
Spring IoC注解式开发无敌详细(细节丰富)
java·后端
小莫分享1 小时前
Java Lombok 入门
java
程序无bug1 小时前
Spring 对于事务上的应用的详细说明
java·后端
食亨技术团队1 小时前
被忽略的 SAAS 生命线:操作日志有多重要
java·后端
苦学编程的谢2 小时前
Maven
java·maven·intellij-idea