java 线程池

线程池的概述:

一种线程使用模式,线程过多会带来调度开销 ,影响缓存局部性和整体性能,**线程池维护着多个线程,**等待着监督管理者分配并发执行的任务,避免了在处理短时间任务时创建与销毁的代价,

线程池不仅能够保证内核的充分利用,还能防止过度调度

线程池的优势:

线程池主要工作控制运行的线程数量 ,处理过程中奖任务放入队列,然后在线程创建后启动这些任务,如果线程数量超过了最大数量,超出的数量的线程排队等候 ,等其他线程执行完毕,然后再从队列中取出任务执行

线程池的特点:

降低支援消耗:通过重复利用已创建的线程降低线程和销毁造成的消耗。

提高响应速度:当任务到达时,任务可以不需要等待线程创建就能立即执行。

提高线程的可管理性:线程是稀缺资源,如果无限制的创建,会消耗系统资源,降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。

java中线程池架构:

java中的线程池通过executor框架实现,主要用到了,executor,executors,executorService,ThreadPoolExecutor

类结构如下

UML类图之间一共有三种形式的连接

1.绿色虚线: 接口-类,表示该类继承了此接口,该类是此接口的实现类。

2.蓝色实线: 类-类,表示一个类继承了另一个类,一个是父类(超类),一个是子类(派生类)。

3.红色实线: 类-类,表示一个类是另一个类的内部类。

线程池常用的使用方式:

1.Executors.newFixedThreadPool(int):一池N线程

2.Executors.newSingleThreadExecutor():一个任务一个任务执行,一池一线程

3.Executors.newCachedThreadPool():线程池根据需求创建线程,可扩展。

newCachedThreadPool理论上可以创建的线程数量接近无限,但实际上受限于系统资源(如CPU和内存)核心数

代码如下:

java 复制代码
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 演示线程池的常用分类
 */
public class ThreadPoolDemo1 {
    public static void main(String[] args) {
//        demo_1();
//        demo_2();
        demo_3();
    }
    /**
     * 一池可扩容的线程池
     */
    public static void demo_3(){
        //一池可扩容的线程池
        ExecutorService executorService = Executors.newCachedThreadPool();
        try {
            for (int i = 0; i < 300; i++) {
                executorService.execute(()->{
                    System.out.println(Thread.currentThread().getName()+"买票");
                });
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            //关闭线程池 但是还是在executorService里
            executorService.shutdown();
        }
    }
    /**
     * 一池一线程
     */
    public static void demo_2(){
        //一池一线程
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        try {
            for (int i = 0; i < 10; i++) {
                executorService.execute(()->{
                    System.out.println(Thread.currentThread().getName()+"买票");
                });
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            //关闭线程池 但是还是在executorService里
            executorService.shutdown();
        }
    }
    /**
     * 一池N线程
     */
    public static void demo_1(){
        //一池5线程
        ExecutorService executorService = Executors.newFixedThreadPool(5);
        //10个顾客来买票
        try {
            for (int i = 0; i < 10; i++) {
                executorService.execute(()->{
                    System.out.println(Thread.currentThread().getName()+"买票");
                });
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            //关闭线程池 但是还是在executorService里
            executorService.shutdown();
        }
    }
}

线程池的5个参数描述(jdk17):

int corePoolSize:常驻线程数

int maximumPoolSize:最大线程数量

long keepAliveTime:线程存活时间

TimeUnit unit:时间分类(秒,毫秒,分。小时)

BlockingQueue<Runnable> workQueue:阻塞队列,如果常驻线程数用完对进入这里面,

线程池的底层工作流程:

标题

1.当前创建线程是会先从核心线程数去拿(1-4),

2.当核心线程数拿完后会走阻塞队列,当阻塞队列的线程也用完了后(5-8),

3.创建新的线程(10-15)

4.当前常驻线程满了,阻塞队列满了,最大线程数满了,就会被拒绝

拒绝策略如下:

CallerRunsPolicy:调用者运行,一种调节机制,该策略既不会抛弃任务,也不会抛出异常,而是将某些任务回退到调用者,从而降低新任务的流量

DiscardOldestPolicy:抛弃队列中等待最久的任务,然后把当前任务加入队列中尝试再次提交当前任务

AbortPolicy:(默认),直接抛出RejectedExecutionException异常阻止系统正常运行

DiscardPolicy:该策略默默地丢弃无法处理的任务,不予任何处理也不抛弃异常,如果允许任务丢失,这是最好的一种策略

自定义线程池:

实际工作工作中都是自定义线程池,

Out Of Memory异常(oom)

java 复制代码
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class ThreadPoolDemo2
{
    public static void main(String[] args) {
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                2,
                3,
                2L,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(10));
        try {
            for (int i = 0; i < 10; i++) {
                executor.execute(()->{
                    System.out.println(Thread.currentThread().getName()+"买票");
                });
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            //关闭线程池 但是还是在executorService里
            executor.shutdown();
        }

    }
}
相关推荐
一只旭宝几秒前
细讲C加加【9】C++ std::function与std::bind详解|仿函数、绑定器、类成员绑定、占位符、成员偏移指针
开发语言·c++·算法
山荷枝1 小时前
03-框架--Spring
java·后端·spring
ChaHae-In2 小时前
SpringBoot统一功能处理
java·spring boot·后端
coder!mq2 小时前
说几个常见的语法糖?
java·开发语言·算法
gugucoding2 小时前
38. 【Java】Stream API(下):高级操作与性能
java·开发语言
Lhan.zzZ2 小时前
在 Visual Studio 2022 中打造可扩展的动态链接库模块:从零搭建到原理解析
开发语言·c++·visual studio
心平气和量大福大3 小时前
android-实例-蒲公英-更新与安装-5-签名与生成APK
android·java·开发语言
码哥DFS3 小时前
构造函数、实例对象、对象原型 ----三者关系
开发语言·javascript·原型模式
952363 小时前
Spring-cloud配置中心
java·spring·spring cloud·微服务
quantdash_cc3 小时前
告别自建 Requests/BS4 网页爬虫:基于 QuantDash 搭建零维保的高性能量化行情流水线
开发语言·爬虫·python·pandas·量化·quantdash