javajava 模拟 实现一个 ThreadPoolExecutor

Posted 九师兄

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了javajava 模拟 实现一个 ThreadPoolExecutor相关的知识,希望对你有一定的参考价值。

1.概述

这里参考:

硬核干货:4W字从源码上分析JUC线程池ThreadPoolExecutor的实现原理

面经手册 · 第21篇《手写线程池,对照学习ThreadPoolExecutor线程池实现原理!》

这里先参考ThreadPoolExecutor的实现并且进行简化,实现一个只有核心线程的线程池,要求如下:

  • 暂时不考虑任务执行异常情况下的处理。
  • 任务队列为无界队列。
  • 线程池容量固定为核心线程数量。
  • 暂时不考虑拒绝策略。
public class ThreadPoolTrader implements Executor 

    private final AtomicInteger ctl = new AtomicInteger(0);

    private volatile int corePoolSize;
    private volatile int maximumPoolSize;

    private final BlockingQueue<Runnable> workQueue;

    public ThreadPoolTrader(int corePoolSize, int maximumPoolSize, BlockingQueue<Runnable> workQueue) 
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
    

    @Override
    public void execute(Runnable command) 
        int c = ctl.get();
        if (c < corePoolSize) 
            if (!addWorker(command)) 
                reject();
            
            return;
        
        if (!workQueue.offer(command)) 
            if (!addWorker(command)) 
                reject();
            
        
    

    private boolean addWorker(Runnable firstTask) 
        if (ctl.get() >= maximumPoolSize) return false;

        Worker worker = new Worker(firstTask);
        worker.thread.start();
        ctl.incrementAndGet();
        return true;
    

    private final class Worker implements Runnable 

        final Thread thread;
        Runnable firstTask;

        public Worker(Runnable firstTask) 
            this.thread = new Thread(this);
            this.firstTask = firstTask;
        

        @Override
        public void run() 
            Runnable task = firstTask;
            try 
                while (task != null || (task = getTask()) != null) 
                    task.run();
                    if (ctl.get() > maximumPoolSize) 
                        break;
                    
                    task = null;
                
             finally 
                ctl.decrementAndGet();
            
        

        private Runnable getTask() 
            for (; ; ) 
                try 
                    System.out.println("workQueue.size:" + workQueue.size());
                    return workQueue.take();
                 catch (InterruptedException e) 
                    e.printStackTrace();
                
            
        
    

    private void reject() 
        throw new RuntimeException("Error!ctl.count:" + ctl.get() + " workQueue.size:" + workQueue.size());
    

    public static void main(String[] args) 
        ThreadPoolTrader threadPoolTrader = new ThreadPoolTrader(2, 2, new ArrayBlockingQueue<Runnable>(10));

        for (int i = 0; i < 10; i++) 
            int finalI = i;
            threadPoolTrader.execute(() -> 
                try 
                    Thread.sleep(1500);
                 catch (InterruptedException e) 
                    e.printStackTrace();
                
                System.out.println("任务编号:" + finalI);
            );
        
    



// 测试结果

任务编号:1
任务编号:0
workQueue.size:8
workQueue.size:8
任务编号:3
workQueue.size:6
任务编号:2
workQueue.size:5
任务编号:5
workQueue.size:4
任务编号:4
workQueue.size:3
任务编号:7
workQueue.size:2
任务编号:6
workQueue.size:1
任务编号:8
任务编号:9
workQueue.size:0
workQueue.size:0
 

以上,关于线程池的实现还是非常简单的,从测试结果上已经可以把最核心的池化思想体现出来了。主要功能逻辑包括:

  • ctl,用于记录线程池中线程数量。

  • corePoolSize、maximumPoolSize,用于限制线程池容量。

  • workQueue,线程池队列,也就是那些还不能被及时运行的线程,会被装入到这个队列中。

  • execute,用于提交线程,这个是通用的接口方法。在这个方法里主要实现的就是,当前提交的线程是加入到worker、队列还是放弃。

  • addWorker,主要是类 Worker 的具体操作,创建并执行线程。这里还包括了 getTask() 方法,也就是从队列中不断的获取未被执行的线程。

好,那么以上呢,就是这个简单线程池实现的具体体现。但如果深思熟虑就会发现这里需要很多完善,比如:线程池状态呢,不可能一直奔跑呀!?、线程池的锁呢,不会有并发问题吗?、线程池拒绝后的策略呢?,这些问题都没有在主流程解决,也正因为没有这些流程,所以上面的代码才更容易理解。

接下来,我们就开始分析线程池的源码,与我们实现的简单线程池参考对比,会更加容易理解😄!

看完这个可以看

先看使用

【高并发】java中的线程池 ThreadPoolExecutor

进阶版

【java】java中的线程池 ThreadPoolExecutor源码分析

进阶版

面经手册 · 第21篇《手写线程池,对照学习ThreadPoolExecutor线程池实现原理!》

以上是关于javajava 模拟 实现一个 ThreadPoolExecutor的主要内容,如果未能解决你的问题,请参考以下文章

javajava 实现 将 字符串 第一个字符 大写 或者 小写

Javajava扩展机制SPI 实现

javajava两个栈实现一个队列&两个队列实现一个栈

javajava 使用 Unsafe CAS 实现数据递增 打印重复问题

javaJava实现异步调用方法(jdk1.8)

javaJava实现单向链表反转