手写java线程池(参考jdk源码)

java线程池

目前只写到能正确创建线程,线程扩容到最大线程数,还没写线程池缩容和shutdown。

能正确运用线程池创建线程并执行任务。

测试和结果

当前测试使用线程池无参构造函数(无参构造器其实本质上调用了 7 参数构造器, 7 参数构造器和 JDK 源码的构造器一样),corePoolSize = 5, maximumPoolSize = 8, 阻塞队列最大容量是16。(如果任务数超过 corePoolSize 且没到阻塞队列容量的 1/4 ,把任务放入阻塞队列等待,否则继续新建线程数直到到达 maximumPoolSize。

22:30:41.336 [main] INFO java.util.concurrent.ThreadFactory - workers number < corePoolsize, create a new worker worker num : 0
22:30:41.343 [main] INFO java.util.concurrent.ThreadFactory - get worker and starting...
22:30:41.343 [main] INFO java.util.concurrent.ThreadFactory - workers number < corePoolsize, create a new worker worker num : 1
22:30:41.343 [main] INFO java.util.concurrent.ThreadFactory - get worker and starting...
22:30:41.343 [main] INFO java.util.concurrent.ThreadFactory - workers number < corePoolsize, create a new worker worker num : 2
22:30:41.343 [main] INFO java.util.concurrent.ThreadFactory - get worker and starting...
22:30:41.343 [main] INFO java.util.concurrent.ThreadFactory - workers number < corePoolsize, create a new worker worker num : 3
22:30:41.344 [main] INFO java.util.concurrent.ThreadFactory - get worker and starting...
22:30:41.344 [main] INFO java.util.concurrent.ThreadFactory - workers number < corePoolsize, create a new worker worker num : 4
22:30:41.344 [main] INFO java.util.concurrent.ThreadFactory - get worker and starting...
22:30:41.344 [main] INFO java.util.concurrent.ThreadFactory - workers number < maximumPoolSize, put in to queue until enough tasks awaiting worker num : 5
22:30:41.345 [main] INFO java.util.concurrent.ThreadFactory - workers number < maximumPoolSize, put in to queue until enough tasks awaiting worker num : 5
22:30:41.345 [main] INFO java.util.concurrent.ThreadFactory - workers number < maximumPoolSize, put in to queue until enough tasks awaiting worker num : 5
22:30:41.345 [main] INFO java.util.concurrent.ThreadFactory - workers number < maximumPoolSize, put in to queue until enough tasks awaiting worker num : 5
22:30:41.345 [main] INFO java.util.concurrent.ThreadFactory - workers number < maximumPoolSize, put in to queue until enough tasks awaiting worker num : 5
22:30:41.345 [main] INFO java.util.concurrent.ThreadFactory - poolSize > awaiting workers number, create new Thread worker num : 6
22:30:41.345 [main] INFO java.util.concurrent.ThreadFactory - get worker and starting...
22:30:41.346 [main] INFO java.util.concurrent.ThreadFactory - poolSize > awaiting workers number, create new Thread worker num : 7
22:30:41.346 [main] INFO java.util.concurrent.ThreadFactory - get worker and starting...
22:30:41.346 [main] INFO java.util.concurrent.ThreadFactory - poolSize > awaiting workers number, create new Thread worker num : 8
22:30:41.346 [main] INFO java.util.concurrent.ThreadFactory - get worker and starting...
22:30:41.346 [main] INFO java.util.concurrent.ThreadFactory - no available workers, put tasks into queue worker num : 8
22:30:41.347 [main] INFO java.util.concurrent.ThreadFactory - no available workers, put tasks into queue worker num : 8

java 代码


package com.xxx.springboot.myThreadPool;

import org.apache.camel.model.GlobalOptionDefinition;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashSet;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class ThreadPool {

    private static final Logger logger = LoggerFactory.getLogger(ThreadFactory.class);

    private final AtomicInteger workCount = new AtomicInteger(0);

    private final AtomicInteger taskCount = new AtomicInteger(0);

    private final BlockingQueue<Runnable> workQueue;

    private final ThreadFactory threadFactory;

    private final int corePoolSize;

    private final int maximumPoolSize;

    private final long keepAliveTime;

    private final RejectedExecutionHandler handler;

    private final HashSet<Worker> workers = new HashSet<>();

    private final int awaitingWorkerNumber;

    /**
     * 锁住 能操作 workers
     */
    private final ReentrantLock mainLock = new ReentrantLock();

    private final Condition termination = mainLock.newCondition();

    private int largestPoolSize;

    private long completedTaskCount;

    /**
     *
     */
    public ThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime,
                TimeUnit unit, BlockingQueue<Runnable> workQueue,
               ThreadFactory threadFactory, RejectedExecutionHandler handler) {
        //logger.info("constructing the ThreadPool class...");
        if (corePoolSize < 0 || maximumPoolSize <= 0 ||
                maximumPoolSize < corePoolSize || keepAliveTime < 0) {
            logger.error("wrong arguments detected...");
            throw new IllegalArgumentException();
        }
        if (workQueue == null || threadFactory == null || handler == null) {
            logger.error("null argument...");
            throw new NullPointerException();
        }
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.awaitingWorkerNumber = workQueue.remainingCapacity() / 4;
        this.handler = handler;
        //logger.info("finish constructing the ThreadPool class...");
    }

    /**
     *  default constructor
     */
    public ThreadPool() {
        this(5, 8, 2000, TimeUnit.MINUTES,
                new ArrayBlockingQueue<Runnable>(16), Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());
        //logger.info("using non-args constructor...");
    }



    public void execute(Runnable command) {
        if (command == null) {
            logger.error("runnable task is null...");
            throw new NullPointerException();
        }

            try {
                mainLock.lock();
                Worker worker = acquireWorker(command);
                if (worker != null) {
                    logger.info("get worker and starting...");
                    worker.execute();
                }
            } catch (Exception e) {
                e.printStackTrace();

            } finally {
                mainLock.unlock();
            }

    }

    private Worker acquireWorker(Runnable command) {
        mainLock.lock();
        try {
            if (workCount.get() < corePoolSize) {
                logger.info("workers number < corePoolsize, create a new worker" + " worker num : " + workCount.get());
                Worker worker = createWorker(command);
                taskCount.set(taskCount.get() + 1);
                return worker;
            } else if (workCount.get() < maximumPoolSize) {
                /**
                 * if awaiting tasks > 1 / 4 Queue.size ,create new worker
                 */
                if (taskCount.get() - workCount.get() <= awaitingWorkerNumber) {
                    workQueue.add(command);
                    taskCount.set(taskCount.get() + 1);
                    logger.info("workers number < maximumPoolSize, put in to queue until enough tasks awaiting" + " worker num : " + workCount.get());
                } else {
                    Worker worker = createWorker(workQueue.take());
                    workQueue.add(command);
                    taskCount.set(taskCount.get() + 1);
                    logger.info("poolSize > awaiting workers number, create new Thread" + " worker num : " + workCount.get());
                    return worker;
                }
            } else {
                try {
                    workQueue.add(command);
                    taskCount.set(taskCount.get() + 1);
                    logger.info("no available workers, put tasks into queue"  + " worker num : " + workCount.get());
                } catch (IllegalStateException e) {
                    e.printStackTrace();
                    logger.warn("workQueue is full, discarding the work..." + " worker num : " + workCount.get());
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.info("error encountered while acquiring worker" + " worker num : " + workCount.get());
        } finally {
            mainLock.unlock();
        }
        return null;
    }

    /**
     *  only accessed by acquireWorker() function
     * @param command
     * @return
     */
    private Worker createWorker(Runnable command) {
        workCount.set(workCount.get() + 1);
        Worker worker = new Worker(command);
        workers.add(worker);
        return worker;
    }


    /**
     *  AQS
     */
    private final class Worker extends AbstractQueuedSynchronizer implements Runnable {

        final Thread thread;

        Runnable firstTask;
        /**
         * 先前执行任务计数器
         */
        volatile long completedTasks;

        Worker(Runnable firstTask) {
            //logger.info("Initializing Workers's constructor... ");
            setState(-1);
            this.firstTask = firstTask;
            this.thread = threadFactory.newThread(firstTask);
        }

        @Override
        public void run() {

        }

        public void execute() {
            //logger.info("Workers is running using " + Thread.currentThread().getName());
            thread.start();
        }


    }



    public String getCurrentTime() {
        StringBuilder res = new StringBuilder();
        long time = new Date().getTime();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
        String format = sdf.format(time);
        res.append(format);
        res.append(" ");
        return res.toString();
    }


}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值