线程池的理解

一、前言

之前我们获取线程池的时候基本上是通过Executors类去调用所需要的线程池;
但这样或多或少的会出现一些问题。

二、线程池

Executors.newSingleThreadExecutor();

   public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }
    
   public LinkedBlockingQueue() {
        this(Integer.MAX_VALUE);
    }

如上所调用的单线程线程池:它的keepAliveTime为0,表示不回收线程,它队列所使用的是LinkedBlockingQueue,默认大小为Integer最大值,意味着队列可以存很多的线程,但每个线程都是要占内存空间的,如果任务过多,很有可能会导致内存溢出这一现象发生。那怎么办?

idea都提示你要手动创建线程池了,你再不手动创建那就天理难容了啊!!!
在这里插入图片描述

三、自定义线程池

从上面可以看出线程池的实现其实主要是由ThreadPoolExecutor类去实现的。

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler)
                              corePoolSize:核心线程数
--- 线程池参数                              
maximumPoolSize:最大线程数
keepAliveTime:空闲线程回收时间间隔
unit:空闲线程回收时间间隔单位
workQueue:提交任务的队列,当线程数量超过核心线程数时,可以将任务提交到任务队列中。比较常用的有:ArrayBlockingQueue; LinkedBlockingQueue; SynchronousQueue;
threadFactory:线程工厂,可以自定义线程的一些属性,比如:名称或者守护线程等
handler:表示当拒绝处理任务时的策略

handler:拒绝策略;默认的拒绝策略为AbortPolicy()

new ThreadPoolExecutor.AbortPolicy():丢弃任务并抛出RejectedExecutionException异常。
new ThreadPoolExecutor.DiscardPolicy():也是丢弃任务,但是不抛出异常。
new ThreadPoolExecutor.DiscardOldestPolicy():丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
new ThreadPoolExecutor.CallerRunsPolicy():由调用线程处理该任务

四、线程池的运行过程

在这里插入图片描述

五、自定义线程池例子

private static final AtomicInteger THREAD_NUMBER = new AtomicInteger();
private static final ExecutorService EXECUTOR_SERVICE = new ThreadPoolExecutor(2,4,10, TimeUnit.MILLISECONDS,
            new LinkedBlockingQueue<>(1000),(Runnable r)->new Thread(r,"SqlPrintInterceptorThread:"+THREAD_NUMBER.getAndIncrement()),
            new ThreadPoolExecutor.DiscardOldestPolicy());

六、源码分析

    public void execute(Runnable command) {
        if (command == null)
            throw new NullPointerException();
        int c = ctl.get();
        //当前线程数是否小于corePoolSize
        if (workerCountOf(c) < corePoolSize) {
        	//添加新线程,true:corePoolSize作为绑定,false:maximumPoolSize
            if (addWorker(command, true))
                return;
            c = ctl.get();
        }
        //线程是否处于Running状态,添加任务到队列(队列没满)
        if (isRunning(c) && workQueue.offer(command)) {
            int recheck = ctl.get();
            //从队列里移除任务
            if (! isRunning(recheck) && remove(command))
            	//执行拒绝策略
                reject(command);
                //当前线程池数量为null
            else if (workerCountOf(recheck) == 0)
                addWorker(null, false);
        }
        //如果队列满了,则新增线程,新增失败则执行拒绝策略
        else if (!addWorker(command, false))
            reject(command);
    }

七、线程池到底有多少个线程在运行

在我初学线程的时候,一度认为最大线程数数量就是线程运行的数量,当我深入了解后,发现线程池的顺序是:

			1、核心线程数------2、队列------3、最大线程数

于是我及时修改自己的想法:核心线程数才是线程运行的数量,而最大线程数是最多有多少个线程数再执行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值