线程池知识点

一、线程池的概述

线程池作用:

线程属于重要的系统资源,创建线程会消耗大量的服务器资源,线程池能够对线程资源进行回收,重复使用,以降低对服务器资源的消耗。

相关的 APl:

线程池顶层接口:Executor ɪɡˈzekjətər

主要方法:execute(Runnable) ˈrʌnəbl 启动线程来执行任务,执行完回收线程

子接口:ExecutorService

主要方法:shutdown() ˈʃʌtdaʊn 停止线程池,会让其中线程继续把任务做完

shutdownNow() 停止线程池,会中断正在执行的线程

实现类:ThreadPoolExecutor 具体线程池的实现类

工具类:Executors 用于快速创建线程池的

二、创建线程池的几种方法

使用 Executors 工具类创建线程池

  • ExecutorService newCachedThreadPool() 获得长度不限的线程池
  • ExecutorService newFixedThreadPool(数量) 长度固定的线程池
  • ExecutorService newSingleThreadExecutor() 获得长度单一的线程池
  • ScheduledExecutorService newScheduledThreadPool(数量) 获得可以调度的线程池

三、手动创建线程池参数

阿里规范要求必须手动创建线程池,不使用 Executor 创建

使用 ThreadPoolExecutor 类创建,构造方法的参数:

1)corePoolSize 核心线程数,创建线程池后池中的线程数量 (核心线程数在线程启动的时候创建,非 核心线程是在线程池运行过程中根据需要动态创建)

2)maxPoolSize 最大线程数,线程池的极限

3)keepAliveTime 保持存活时间,空闲线程的存活时间

4)timeUnit 时间单位

5)workQueue 工作队列,阻塞队列用于保存执行任务 Runnable

6)threadFactory 线程工厂,用于创建线程

7)rejectHandler 拒绝策略,处理暂时执行不了的任务

线程池的配置:

1)核心线程数,要考虑当前任务情况,是 计算密集型(大量使用 CPU)还是 IO 密集型(大量进行数据 IO)

计算密集性:需要充分利用 CPU 内核,线程数量=CPU内核,获得方法:runtime.getRuntime().availableProcessors();

IO密集型:耗时的IO操作会造成线程长时间阻塞,需要更多的线程,线程数量 = CPU * n( n>=2 n 的大小取决于 IO 操作耗时情况和请求总数) 具体通过压力测试

2)最大线程数,可以设置和核心线程数一样,就避免频繁创建线程和销毁线程的消耗

3)存活时间,如果说 核心线程数 和 最大线程数 一样,可以设置为 0,如果不一样,尽量设置长一点,避免频繁创建和销毁

4)阻塞队列,可以使用 linkedBlockingQueue ,添加和删除任务的效率高

//        操作系统相关的类
Runtime runtime = Runtime.getRuntime();
//  打开剪切板
runtime.exec("mspaint");
//	获取本机cpu内核数
int cpuNum = runtime.getRuntime().availableProcessors();
System.out.println("cpu内核数:" + cpuNum);

手动创建线程池案例

 /**
 * 自定义的线程池
 */
public static void testThreadPoolExecutor() {
//        获得内核数
    int cpuNum = Runtime.getRuntime().availableProcessors() * 2;

//        手动创建线程池
    ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(cpuNum, cpuNum, 0, TimeUnit.SECONDS,
                                                                   new LinkedBlockingQueue<>());

    for (int i = 0; i < 1000; i++) {
//            使用线程池启动线程
        threadPoolExecutor.execute(() -> {
            System.out.println(Thread.currentThread().getName() + "执行了");
        });
    }
//        关闭线程池
    threadPoolExecutor.shutdown();
}

四、线程池的原理

线程池如何回收线程?在线程执行完任务后,不死亡。

ThreadPoolExecutor 类中有内部类 Worker 代表工作线程,内部保证 Thread 所有工作线程保存在 HashSet

/**
* Set containing all worker threads in pool. Accessed only when
* holding mainLock.
*/
private final HashSet<Worker> workers = new HashSet<Worker>();

线程池工作原理:execute 方法

1)执行 execute方法传入 Runnable 对象

2)判断当前线程有没有达到核心线程数

3)没有就添加核心线程,有再判断是否达到最大线程数

4)达到最大值就执行拒绝策略

5)添加线程时,创建 Worker 工作线程,启动工作线程

6)执行 runWorker 方法,会循环调用 getTask()从工作队列取任务

7)取到任务就执行,如果任务取空,线程就被阻塞,直到有新任务

  • 22
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值