前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【多线程】线程池源码(3)

【多线程】线程池源码(3)

作者头像
用户8902830
发布2021-08-10 11:57:52
2650
发布2021-08-10 11:57:52
举报
文章被收录于专栏:CodeNone

线程池的源码解读就先告一段落了(其实总感觉缺了什么东西,但是又找不到),本篇文章就简单总结下之前讲的流程及一些用法。

1 线程池流程图

通过两篇文章,可能分开来看每一部分都能看懂,但是总的一个流程没有串联起来,下面看下整体的一个流程图

2 综合例子

接下来再通过一个综合例子对一些知识点进行回顾

2.1 自定义ThreadPoolExecutor

首先自定义ThreadPoolExecutor,然后重写beforeExecute()afterExecute() 方法

代码语言:javascript
复制
public class MyThreadPoolExecutor extends ThreadPoolExecutor {
    //省略必须要实现的父类的构造函数,4个

    @Override
    protected void beforeExecute(Thread t, Runnable r) {
        System.out.println("【before execution】" + r.toString());
    }

    @Override
    protected void afterExecute(Runnable r, Throwable t) {
        System.out.println(r.toString() + "【after execution】");
    }
}

❝注意,是省略了构造函数,一般IDE都会提示报错,「至少需要实现一个」

2.2 自定义RejectedExecutionHandler

自定义拒绝策略,现在没有具体的需求,说好听的是自定义拒绝策略,不好听就是单纯地硬实现而已。

代码语言:javascript
复制
public class MyRejectedExecutionHandler implements RejectedExecutionHandler {

    @Override
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
        System.out.println("task is rejected");
    }
}

甚至对任务都没做任何处理,只是单纯的控制台输出了一句话。

2.3 监控线程池状态的线程

在一开始也普及过了线程池中相关的一些参数,通过下面这个监视线程能更加直观的了解这些参数

代码语言:javascript
复制
public class MonitorThread implements Runnable {

    private ThreadPoolExecutor executor;


    public MonitorThread(ThreadPoolExecutor executor) {
        this.executor = executor;
    }

    private boolean monitor = true;

    public void stopMonitor() {
        monitor = false;
    }

    @Override
    public void run() {
        while (monitor) {
            System.out.println(
                    String.format("[monitor] [%d/%d] Active: %d, Completed: %d, Task: %d, isShutdown: %s, isTerminated: %s, rejectedExecutionHandler: %s",
                            this.executor.getPoolSize(),
                            this.executor.getCorePoolSize(),
                            this.executor.getActiveCount(),
                            this.executor.getCompletedTaskCount(),
                            this.executor.getTaskCount(),
                            this.executor.isShutdown(),
                            this.executor.isTerminated(),
                            this.executor.getRejectedExecutionHandler()));

            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
2.4 自定义的线程

估计过了这么久了,各位小伙伴也都忘记最初线程初体验开始创建的类了,这里再重复一遍。

代码语言:javascript
复制
public class MyThread implements Runnable {

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + " processing");
        process();
        System.out.println(Thread.currentThread().getName() + " end");
    }

    private void process() {
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Override
    public String toString() {
        return String.format("MyThread{%s}", Thread.currentThread().getName());
    }
}

❝这个虽然是线程,但是在线程池里面其实是看作一个任务,线程池会创建核心线程来执行这个任务(逻辑是这个线程里面的run()方法)。 ❞

2.5 测试类

有了以上这些后,就可以开始我们的测试了

代码语言:javascript
复制
public class ThreadPoolInfo {
    public static void main(String[] args) throws InterruptedException {
        MyThreadPoolExecutor executor = new MyThreadPoolExecutor(3,5, 30, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(3), new MyRejectedExecutionHandler());
        MonitorThread monitorThread = new MonitorThread(executor);
        //开启监控线程
        new Thread(monitorThread).start();
        for (int i = 0; i < 10; i++) {
            //开启工作线程
            executor.execute(new MyThread());
        }

        Thread.sleep(12000);
        executor.shutdown();
        Thread.sleep(3000);
        monitorThread.stopMonitor();
    }
}

3 测试

首先看下整体的运行的结果gif动图

可以看到有前后置执行策略,也有拒绝策略,以及线程池的相关状态等,接下来通过截图仔细看一下

至于线程池的状态如下

这里再说下,task数 = 队列的长度 + 最大线程数 原因的话如果前面有仔细阅读源码解析应该是知道的,这里再说一下

「队列的长度」 ,看execute中的代码

「最大线程数」 ,看addWorker

「简单来说就是当wc(工作线程数)达到最大也就是maximumPoolSize的时候,此时任务队列也忙了,这时候就是能承受的最大任务。」

结语

java多线程中的线程池到这就告一段落啦,这些理论只是相对简单的,线程池的复杂是涉及到操作系统底层的了,是基本不可能预测到操作系统是要运行哪个线程的,写这些理论知识是在我们可控的层面尽可能多地去理解它。

用下面这张图来做个总结叭,「你理想的线程池 vs 真正的线程池」

图片来自网络,侵删

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-07-31,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 CodeNone 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1 线程池流程图
  • 2 综合例子
    • 2.1 自定义ThreadPoolExecutor
      • 2.2 自定义RejectedExecutionHandler
        • 2.3 监控线程池状态的线程
          • 2.4 自定义的线程
            • 2.5 测试类
            • 3 测试
            • 结语
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档