自定义线程池参数及原理讲解

线程池参数

在这里插入图片描述

  • corePoolSize:核心线程池数量
  • maximumPoolSize:最大线程池数量
  • keepAliveTime:非核心线程的空闲状态的存活时间
  • util:单位时间(天,小时,秒)
  • workqueue:工作队列(阻塞队列)
  • threadFactory:线程工厂(作用:创建线程)
  • handler:拒绝策略
    • ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常
    • ThreadPoolExecutor.DiscardPolicy:丢弃任务但不抛出异常
    • ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务
    • ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务

线程池运行原理

在这里插入图片描述
注: 创建:先创建核心线程,再放到阻塞队列,再创建非核心线程 执行:先用核心线程执行,再用非核心执行,最后阻塞队列(执行过程是非公平的)

示例

public class CustomThreadPool {
    public static void main(String[] args) {
        ExecutorService threadPool = new ThreadPoolExecutor(
                10,
                20,
                0l,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(10),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy()
        );

        class MyTask implements Runnable {
            int i = 0;

            public MyTask(int i) {
                this.i = i;
            }

            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + "程序员做第" + i + "个项目");
                try {
                    Thread.sleep(3000l);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        try {
            for (int j = 0; j < 100; j++){
                MyTask task = new MyTask(j);
                threadPool.execute(task);
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            threadPool.shutdown();
        }
    }
}

在这里插入图片描述
从打印可以看出:
创建:先创建核心线程,再放到阻塞队列,再创建非核心线程
执行:先用核心线程执行,再用非核心执行,最后阻塞队列(执行过程是非公平的)`

源码分析

1

public class ThreadPoolTest {
    public static void main(String[] args) {
    //构建一个线程池,此时没有创建线程
        ExecutorService executor = new ThreadPoolExecutor(
                10,
                200,
                0l,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(10),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy()
        );
        //提交一个任务到线程池
        executor.execute(new Runnable() {
            @Override
            public void run() {
                System.out.println("zhangsan...");
            }
        });
    }
}

1.跟进execute方法:

在这里插入图片描述

2.addWorker()创建一个线程,然后使用start()`启动线程

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.假设提交4个任务,第一个任务执行完了,是新建一个线程执行,还是使用第一个任务执行完的线程执行呢?

在这里插入图片描述

  • 从源码可以看出(workerCountOf(c):计算当前线程数),如果当前线程数小于核心,则新建线程执行:
    在这里插入图片描述

4.如果线程1执行完了,会销毁还是存活?

  • 伪代码
    会到阻塞队列获取任务,如果队列为空,则阻塞。
    在这里插入图片描述

5.新提交的第11任务,调offer()放到阻塞队列

在这里插入图片描述
然后核心线程取获取阻塞队列任务执行。注:并不是直接丢给核心线程去执行,主要是为了线程执行完任务利用阻塞队列保活,这也是设计的奇妙之处。

6.阻塞队列满后,addWorker()新创建线程执行

队列是满的,新建线程却执行新的任务,而不是队列任务,可见线程池是非公平的。
在这里插入图片描述

7.阻塞队列满且最大线程数达到,则掉用reject()拒绝

在这里插入图片描述

8.四种拒绝策略

在这里插入图片描述

AbortPolicy

默认拒绝策略,抛出异常。
在这里插入图片描述

CallerRunsPolicy

调用方执行。
在这里插入图片描述

DiscardOldestPolicy

取出队列最前面一个任务,出队列,然后执行当前任务。
在这里插入图片描述

DiscardPlicy

空方法,啥也不做
在这里插入图片描述

9.线程池淘汰策略?

正常执行完

在这里插入图片描述
在这里插入图片描述

task.run();:执行真正调用者的run();
getTask():从阻塞队列里面获取任务
runWorker():线程池运行提交的一个任务
大于核心数:
如果阻塞队列没有任务,compareAndDecrementWorkerCount():cas淘汰一个线程
有任务,workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS)
小于等于核心数:
如果阻塞队列没有任务, workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) 则返回继续执行。否则核心线程阻塞,workQueue.take();等待任务提交

异常退出

线程执行异常退出,抛出异常。
抛出异常后,会调用processWorkerExit(w, completedAbruptly)重新创建一个线程。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

线程池关闭

shutdown():执行完阻塞队列线程和正在运行的线程,再关闭。
showdownNow():执行完正在运行的线程,就关闭,不执行阻塞队列任务。

  • 线程两种情况:
    • 第一种,正在运行任务
      第一步调用 shutdown():advanceRunState(SHOTDOWN),
      调用 shutdownNow():advanceRunState(STOP),
      设置正在执行任务线程状态。
      第二步:发送一个中断信号,interruptIdleWorkers(),是否执行终端,由执行任务的方法决定。
    • 第二种 take()方法阻塞任务:
      阻塞队列take()根据中断信号,中断阻塞队列线程

在这里插入图片描述
在这里插入图片描述

![!](https://i-blog.csdnimg.cn/direct/42fa303461ed4feaa6409b475add8be9.png)

扩展 异常推出回调机制:uncaughtException(Thread t,Throwable e);

线程异常执行推出,会回调uncaughtException()方法。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值