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

1 线程池流程图

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

2 综合例子

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

2.1 自定义ThreadPoolExecutor

首先自定义ThreadPoolExecutor,而后重写beforeExecute()afterExecute() 办法

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

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

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

甚至对工作都没做任何解决,常识单纯的控制台输入了一句话。

2.3 监控线程池状态的线程

在一开始也遍及过了线程池中相干的一些参数,通过上面这个监督线程能更加直观的理解这些参数

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 自定义的线程

预计过了这么久了,各位小伙伴也都遗记最后线程初体验开始创立的类了,这里再反复一遍。

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 测试类

有了以上这些后,就能够开始咱们的测试了

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 真正的线程池