线程池的7个核心参数和底层原理

62 篇文章 1 订阅

代码使用

public class A implements Runnable{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"开始");
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

    }
}
package com.dmg.ds.entity;
import java.util.concurrent.*;

public class B {

    public static void main(String[] args) {
        //获取线程池
        ThreadPoolExecutor threadPool=threadPoolExecutor();
        for (int i = 0; i <5; i++) {
            A a=new A();
            //执行任务
            threadPool.execute(a);
            int size=threadPool.getQueue().size();
            System.out.println("阻塞队列的长度:"+size);
            System.out.println();
        }
        System.out.println("主线程结束");
    }

    //自定义线程池 7个核心参数
    public static ThreadPoolExecutor threadPoolExecutor(){
        //核心线程数
        int corePoolSize=2;
        //最大线程数=核心线程数+非核心线程数
        int maximumPoolSize=3;
        //存活时间 时间到了之后 就把这个线程销毁掉 重新创建线程 释放资源
        long keepAliveTime=10;
        //存活时间单位 秒
        TimeUnit unit=TimeUnit.SECONDS;
        //链表阻塞队列 当线程超过核心线程数 那么把任务放入阻塞队列中 排队
        BlockingQueue<Runnable> workQueue=new LinkedBlockingQueue<>(1);
        //默认线程工厂 使用线程工厂来创建线程
        ThreadFactory threadFactory=Executors.defaultThreadFactory();
        //拒绝策略
        RejectedExecutionHandler handler=new ThreadPoolExecutor.DiscardPolicy();
        return new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);
    }
}

4种拒绝策略

DiscardPolicy 丢掉当前的任务
DiscardOldestPolicy 丢弃队列第一个任务
AbortPolicy 抛出异常
CallerRunsPolicy 谁调用谁执行

源码分析

 内部使用了可重入锁和条件队列,还有一个子类Worker

 

Worker继承了AQS 实现了Runable接口

在new 对象的时候 会通过线程工厂去创建线程

 在执行任务这里

判断已有的线程数据是否大于核心线程数

如果没有大于 那么继续创建线程

如果大于 那么双重检查线程是否是运行中,并把当前线程加入到阻塞队列中

如果创建线程失败 那么执行拒绝策略

在创建工作节点这里 

会先进行状态的校验 判断是否是运行中的

然后把runable放入工作节点中 去创建线程

然后通过可重入锁进行加锁,在代码执行完毕 释放锁

然后把创建好的工作节点 放入hashset中 

然后执行线程的start方法去启动线程 就会触发run方法

在下面的拒绝策略中,就是又调用了runable的run方法

如果你是mian线程调用,那么触发的拒绝策略就是由main线程执行

在你的A类打印的时候 显示的线程名称就是main

 在下面的拒绝策略中 就是抛出了一个异常

在下面的拒绝策略中 就是什么都不管,空方法,也就是丢弃当前的任务

在下面的拒绝策略中,如果线程池还运行着

那么从队列的头部 取出第一个元素,然后删除

然后再使用线程池去执行任务

总结 


1.在初始化的时候,会创建核心线程数,放入线程池中
2.当有新的任务进来,就从线程池中取出空闲线程并执行任务
3. 如果当前没有空闲线程,那么判断已经创建的线程数是否小于核心线程数
4.如果小于核心线程数,那么创建新的核心线程
5.如果不小于核心线程数,那么把当前任务加入到阻塞队列中
6.如果阻塞队列满了,那么创建非核心线程
7.当非核心线程,出现了空闲,并且空闲时间超过了设置的空闲时间,那么就会被回收
8.如果最大线程数+阻塞队列的容量都满了,这时在进来新的任务,就会执行拒绝策略

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值