自定义线程池-线程池源码笔记

池化技术

池化技术在java中有广泛的运用,比如数据库连接池,字符串池,以及线程池。之所以池化技术运用广泛,在于他的优势以线程池为例):

  • 提高线程的利用率
  • 提高响应速度
  • 便于统一管理线程对象
  • 可控制最大并发数

线程池的设计思想

  • 核心池大小
  • 线程池最大容量
  • 等待队列
  • 拒绝策略

在这里插入图片描述业务流程如下:

线程池启动的时候会按照核⼼池的数来创建初始化的线程对象 2 个。
开始分配任务,如果同时来了多个任务, 2 个线程对象都被占⽤了,第 3 个以及之后的任务进⼊等待队列,当前有线程完成任务恢复空闲状态的时候,等待队列中的任务获取线程对象。
如果等待队列也占满了,⼜有新的任务进来,需要去协调,让线程池再创建新的线程对象,但是线程池不可能⽆限去创建线程对象,⼀定会有⼀个最⼤上限,就是线程池的最⼤容量。
如果线程池已经达到了最⼤上限,并且等待队列也占满了,此时如果有新的任务进来,只能选择拒绝,并且需要根据拒绝策略来选择对应的⽅案。

线程池代码理解

1.Executors工具类的使用:
  1. ExecutorService e= Executors.newSingleThreadExecutor();(单线程)
    在这里插入图片描述
  2. ExecutorService executorService =Executors.newFixedThreadPool(5);(固定数量现线程池)
    在这里插入图片描述
  3. ExecutorService executorService = Executors.newCachedThreadPool();(缓存,线程数油电脑配置定)
    在这里插入图片描述

看上述三个Executors工具类源码可发现他们有一个共同点:都是要new一个ThreadPoolExecutor 对象。ThreadPoolExecutor就是我们要重点理解的。

2.ThreadPoolExecutor

进入此类发现有许多不同参数的构造器,以便使用者灵活 创建自己需要的线程池。其中最重要的是理解7个参数:

corePoolSize:核⼼池的⼤⼩
maximumPoolSize:线程池的最⼤容量
keepAliveTime:线程存活时间(在没有任务可执⾏的情况下),必须是线程池中的数量⼤于
corePoolSize,才会⽣效
TimeUnit:存活时间单位
BlockingQueue:等待队列,存储等待执⾏的任务
ThreadFactory:线程⼯⼚,⽤来创建线程对象
RejectedExecutionHandler:拒绝策略

四种拒绝策略:

1、AbortPolicy:直接抛出异常
2、DiscardPolicy:放弃任务,不抛出异常
3、DiscardOldestPolicy:尝试与等待队列中最前⾯的任务去争夺,不抛出异常
4、CallerRunsPolicy:谁调⽤谁处理

代码实验

已知以上概念,我们可以很轻易地写出自己想要的线程池。
主要代码:

package com.blog.www.common;

import java.util.Collection;
import java.util.List;
import java.util.concurrent.*;

/**
 * @version 1.0
 * @date 2020/3/8 21:37
 */
public class test {
    public static void main(String[] args) {
        //定制化线程池
        ExecutorService executorService = new ThreadPoolExecutor(2,3,0L,TimeUnit.MILLISECONDS,new ArrayBlockingQueue<>(2),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());

        for(int i=0;i<1;i++){
            executorService.execute(()->{
                try {
                    TimeUnit.MILLISECONDS.sleep(100);
                }catch (InterruptedException e){
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"===>办理业务");
            });
        }
    }
}

1.i<1时,单线程结果很明显:
在这里插入图片描述2、i<2时候,此时正好达到核心线程数(结果不唯一)
在这里插入图片描述3、i<3时,for是并发的,第三个任务来会进入等待队列,不会新开线程。
在这里插入图片描述4、i<4时,和上面相同,只不过等待队列刚好满了
5、i<5时,第五个任务来了,此时两个核心线程在运行,等待队列也满了,所以线程池会再创建一个线程,此时就达到我们设置的最大线程上限了。
在这里插入图片描述
6.i<6时,第六个任务来了,此时等待队列满了,也已达到最大线程上限。故只有拒绝此任务。
在这里插入图片描述7.i<7时,第七个任务来了。因为拒绝了第六个任务,同时也有其他任务结束的,故第七个任务也有可能正常执行,当然也有可能被拒绝。这里要改一下主代码,因为决绝策略用的是AbortPolicy直接抛出异常,这样看不出来效果。换成CallerRunsPolicy:谁调⽤谁处理。
在这里插入图片描述8.i<8时,多一点就可以看出来,后面的任务还有可能被执行的。
在这里插入图片描述
至此,定制线程池成功!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值