简易版线程池——模仿ThreadPoolExecutor

简易版线程池

一切尽在代码中。。。

线程池类

/**
 * @Author Mr.wei
 * @Date 2020/2/18 15:00
 * @Description:没有核心线程与非核心线程概念、删减了状态(RUNNING、SHUTDOWN、STOP、TIDYING、TERMINATED)、没添加结束方法......
 */
public class CThreadPoolExecutor {
    /**
     * 线程池大小
     */
    private int poolSize;

    /**
     * 线程存活时间
     */
    private int keepAlive;

    /**
     * 时间单位
     */
    private TimeUnit unit;

    /**
     * 存放任务的阻塞队列
     */
    private BlockingQueue<Runnable> queue;

    /**
     * 拒绝策略
     */
    private CRejectPolicy rejectPolicy;

    /**
     * 线程工厂
     */
    private ThreadFactory threadFactory;

    /**
     * 完成任务数
     */
    private volatile long completeTaskCount;

    /**
     * 主锁
     */
    private ReentrantLock mainLock = new ReentrantLock(true);

    /**
     * 工作者集合
     */
    private HashSet<Worker> workerSet = new HashSet<>();

    /**
     * 工作线程计数器
     */
    private AtomicInteger ctl = new AtomicInteger(0);

    public CThreadPoolExecutor(int poolSize, int keepAlive, TimeUnit unit, BlockingQueue queue, CRejectPolicy rejectPolicy) {
        this.poolSize = poolSize;
        this.keepAlive = keepAlive;
        this.unit = unit;
        this.queue = queue;
        this.rejectPolicy = rejectPolicy;
        this.threadFactory = new DefaultThreadFactory();
    }

    public CThreadPoolExecutor(int poolSize, int keepAlive, TimeUnit unit, BlockingQueue queue, CRejectPolicy rejectPolicy, ThreadFactory threadFactory) {
        this.poolSize = poolSize;
        this.keepAlive = keepAlive;
        this.unit = unit;
        this.queue = queue;
        this.rejectPolicy = rejectPolicy;
        this.threadFactory = threadFactory;
    }

    private class Worker implements Runnable {
        /**
         * 线程
         */
        private Thread thread;

        /**
         * 第一个唤醒该线程的任务
         */
        private Runnable firstTask;

        /**
         * 该工作者完成的任务数
         */
        private int completeTaskCount = 0;

        Worker(Runnable firstTask) {
            this.thread = threadFactory.creatThread(this);
            this.firstTask = firstTask;
        }

        @Override
        public void run() {
            runWorker(this);
        }

    }

    /**
     * 通过worker中的线程执行的任务,其种类有两种:
     * 1. worker中的第一个任务
     * 2. 从queue中取得任务
     * 没有任务的话超过一定的时间就自动消除。
     *
     * @param worker
     */
    private void runWorker(Worker worker) {
        Runnable task = worker.firstTask;
        worker.firstTask = null;
        //判断任务时正常结束,还是因为异常结束
        boolean completedAbruptly = true;
        try {
            //获取任务并执行,这个while是线程复用的精髓,其中getTask是精髓中的精髓
            while (task != null || (task = getTask()) != null) {
                try {
                    task.run();
                } finally {
                    task = null;
                    completeTaskCount++;
                }
            }
            completedAbruptly = false;
        } finally {
            processWorkerExit(worker, completedAbruptly);
        }
    }

    /**
     * 任务的结束
     *
     * @param w
     * @param completedAbruptly
     */
    private void processWorkerExit(Worker w, boolean completedAbruptly) {
        int i = ctl.get();
        if (completedAbruptly) {
            decrementCtl(i);
        }
        ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            completeTaskCount += w.completeTaskCount;
            workerSet.remove(w);
        } finally {
            mainLock.unlock();
        }

        //如果不是正常结束,且队列里不为空,且线程池中线程数还未上限则增加一个线程
        if (completedAbruptly && !queue.isEmpty() && i < poolSize) {
            addWorker(null);
        }
    }

    /**
     * 从队列中获取任务
     *
     * @return
     */
    private Runnable getTask() {
        boolean timeOut = false;
        for (; ; ) {
            //如果队列是空的,并且已经超过了空闲时间,那就减小线程数
            if (queue.isEmpty() && timeOut) {
                decrementCtl(ctl.get());
                return null;
            }

            try {
                Runnable r = queue.poll(keepAlive, unit);
                if (null != r) {
                    return r;
                }
                timeOut = true;
            } catch (InterruptedException e) {

            }
        }
    }

    /**
     * 减少工作线程数
     *
     * @param expect
     */
    private void decrementCtl(int expect) {
        do {
        } while (!ctl.compareAndSet(expect, expect - 1));
    }

    /**
     * 增加工作线程数
     *
     * @param expect
     */
    private boolean incrementCtl(int expect) {
        return ctl.compareAndSet(expect, expect + 1);
    }

    /**
     * 该方法有三种情况:
     * 1. 当线程池中线程数没超过指定线程数,则使用直接addworker
     * 2. 当线程池中的线程满了,但队列没满时,则添加到队列
     * 3. 当线程池和队列都满了,按照给定的策略去执行
     *
     * @param r
     */
    public void execute(Runnable r) {
        if (null == r) {
            throw new NullPointerException();
        }

        if (ctl.get() < poolSize) {
            addWorker(r);
        } else if (queue.offer(r)) {
            if (ctl.get() == 0) {
                addWorker(null);
            }
        } else {
            rejectPolicy.reject(r);
        }

    }

    /**
     * 添加Worker
     *
     * @param r
     * @return
     */
    private boolean addWorker(Runnable r) {
        Worker worker = new Worker(r);
        ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        boolean workerAdded = false;
        boolean workerStarted = false;


        for (; ; ) {
            int c = ctl.get();
            //判断线程数量是否已经达到线程池指定大小
            if (c == poolSize) {
                return false;
            }
            //这里说明线程数量没有达到线程池指定大小,尝试去增加线程大小
            if (incrementCtl(c)) {
                break;
            }
        }
        try {
            try {
                // 向worker集中添加除worker
                workerSet.add(worker);
                workerAdded = true;
            } finally {
                mainLock.unlock();
            }
            //  添加成功就启动线程
            if (workerAdded) {
                Thread thread = worker.thread;
                thread.start();
                workerStarted = true;
            }
        } finally {
            // 启动线程失败之后的处理
            if (!workerStarted) {
                addWorkerFailed(worker);
            }
        }

        return workerStarted;
    }

    /**
     * 添加失败,处理两步走:
     * 1. 从worker集中移除worker
     * 2. 减少线程数
     *
     * @param worker
     */
    private void addWorkerFailed(Worker worker) {
        ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            workerSet.remove(worker);
            decrementCtl(ctl.get());
        } finally {
            mainLock.unlock();
        }
    }
}

 线程工厂

接口

/**
 * @Author Mr.wei
 * @Date 2020/2/18 15:25
 * @Description:线程工厂接口
 */
public interface ThreadFactory {

    /**
     * 创建线程
     *
     * @return 创建好的线程
     */
    public Thread creatThread(Runnable runnable);
}

实现类

/**
 * @Author Mr.wei
 * @Date 2020/2/18 15:31
 * @Description:默认线程工厂
 */
public class DefaultThreadFactory implements ThreadFactory {
    /**
     * 记录当前是第几个线程池
     */
    private static final AtomicInteger poolNum = new AtomicInteger(0);
    /**
     * 记录当前线程是线程池中的第几个线程
     */
    private final AtomicInteger threadNum = new AtomicInteger(0);
    /**
     * 线程名格式
     */
    private final String threadNameFormat;

    public DefaultThreadFactory() {
        threadNameFormat = "Pool-" + poolNum.incrementAndGet() + "-thread-";
    }

    @Override
    public Thread creatThread(Runnable runnable) {
        Thread thread = new Thread(runnable, threadNameFormat + threadNum.incrementAndGet());
        return thread;
    }
}

拒绝策略

接口

/**
 * @Author Mr.wei
 * @Date 2020/2/18 15:21
 * @Description:拒绝策略的接口
 */
public interface CRejectPolicy {

    /**
     * 当任务满了之后的处理策略
     * @param r
     */
    public void reject(Runnable r);

}

实现类

/**
 * @Author Mr.wei
 * @Date 2020/2/18 18:14
 * @Description:默认拒绝策略
 */
public class ExceptionRejectPolicy implements CRejectPolicy {
    /**
     * 当线程池中的线程和队列都满了,就打印消息
     * @param r
     */
    @Override
    public void reject(Runnable r) {
        System.out.println("队列已满!");
    }
}

使用

/**
 * @Author Mr.wei
 * @Date 2020/2/18 18:13
 * @Description:测试Pool
 */
public class TestPool {
    public static void main(String[] args) {
        CThreadPoolExecutor cThreadPoolExecutor = new CThreadPoolExecutor(5, 0, TimeUnit.SECONDS, new ArrayBlockingQueue(4), new ExceptionRejectPolicy());

        for (int i = 0; i < 11; i++) {
            cThreadPoolExecutor.execute(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName());
                    try {
                        Thread.sleep(5);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
        }
    }
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值