手写Java线程池_超详细解说_绝对能运行_代码超详细注释

线程池

问题背景

只是单纯使用 new Thread(runnable).start(); 的方式创建线程, 将会导致严重的程序性能问题: 1.线程创建, 销毁需要消耗很大的系统资源; 2.虚拟机创建线程的数量是有限的; 2.线程调度切换也将使程序性能下降; 针对这些问题, 对线程数量进行管理, 有效地重复利用线程, 将会很好地提高程序性能.

线程池原理

使用队列创建一定数量的线程, 当有任务的时候, 使用队列中线程执行任务(如果任务过多, 就将其放入任务队列, 进入等待执行状态), 任务执行完就自动回收线程队列中的线程(任务过少或者任务数量小于线程数量, 超出的线程将会销毁, 做到线程队列具有伸缩性);

根据上面描述, 我们自己的线程池将具有一下特点:
1.内部使用队列来管理线程, 管理提交的任务.
2.控制线程数量, 做到线程队列具有良好的伸缩性.
3.当任务数过多, 或者任务队列已经饱和, 将使用任务拒绝策略, 告诉对应的任务提交者.
4.使用线程工厂定制线程队列中, 每个线程的名字, 状态, 是否为守护线程等等.

线程池类图结构

  1. 任务队列, 队列使用limit限制提交任务的大小, 实现RunnableQueue接口(RunnableQueue接口负责: 1.接收用户提交的任务; 2.获取任务队列中的任务; 3.查看任务队列大小), LinkedRunnableQueue实现RunnableQueue中的方法, 并且针对用户提交不同的任务以及线程池种类(ThreadPool)的不同, 决定是否执行拒绝策略(拒绝策略具有多个, 拒绝方式取决于用户自定义, 在线程池内部具有默认的拒绝策略实现);
    在这里插入图片描述

  2. 实现Runnable接口, 在run方法中获取RunnableQueue中的任务, 然后执行RunnQueue中的任务, InternalTask中的run方法是一个while循环循环结束条件取决于是否关闭该线程(关闭线程据需要设置flag变量, 当flage为false, 线程run方法结束, 自动结束生命), 而不是当前用户提交的任务是否执行完!!!; InternalTask主要是对RunnableQueue的一种封装; stop方法主要是设置线程flag(flag主要判断当前线程是否关闭)
    在这里插入图片描述

  3. 线程池原型:
    1.实现Runnable接口(此处注明, BasicThreadPool是继承Thread, 但是Thread内容太多了不能很好地在UML图中显示, 所以我就把他删除了, 只留下了实现Runnable接口), 因为线程池自身执行也需要一个线程, 所以继承Thread, 这样可以在BasicThreadPool的构造方法中执行start(), run方法中执行创建线程的操作(线程池内部执行任务的线程); 创建线程取决于线程池设置的最大线程数, 核心线程数, 初始化线程数, 用户提交的任务数;

    2.实现ThreadPool接口(该接口主要用于定义线程池的基本操作, 比如执行任务, 获取线程池的一些基本属性) ;

    3.内部具有2个内部类(ThreadTask负责对InternalTask进行封装, DefaultThreadFactory主要定义默认的线程创建方式), 不同的线程池中拥有不同的默认创建方式, 因此将线程创建方式设置为内部类;

    4.在BasicThreadPool中使用newThread方法创建线程(这些线程用于执行ThreadTask中的任务);

    5.线程池原型中具有2个队列, 第一个是刚才上面提的RunnQueue(负责执行的任务), 第二个是ThreadQueue(负责存储创建的每一个线程, 使用ArrayQueue实现, 这样很好地维护管理了线程, 做到资源重用)

    6.removeThread方法: 删除多余的线程, 当用户提交的任务数量小于线程池中创建的线程数量, 那么就删除一定数量的线程, 这样才不会浪费线程资源.

    7.在构造方法中设置基本属性, 以及当前线程池的拒绝策略.
    在这里插入图片描述

每个接口, 类的详细定义

ThreadPool(interface 定义线程池基本操作)

package com.concurrent.customthreadpool;

/**
 * 线程池接口
 * @author regotto
 */
public interface ThreadPool {
   
    
    /**
     * 执行提交的Runnable任务
     * @param runnable
     */
    void execute(Runnable runnable);
    
    /**
     * 关闭线程池
     */
    void shutdown();
    
    /**
     * 获得线程池初始化大小
     * @return initSize
     */
    int getInitSize();
    
    /**
     * 获得线程池最大线程数
     * @return maxSize
     */
    int getMaxSize();
    
    /**
     * 获取线程池核心线程数
     * @return coreSize
     */
    int getCoreSize();
    
    /**
     * 获取线程池中用于缓存任务队列的大小
     * @return queueSize
     */
    int getQueueSize();
    
    /**
     * 获取线程池中国活跃的线程数量
     * @return activeCount
     */
    int getActiveCount();
    
    /**
     * 查看线程池是否shutdown
     * @return boolan
     */
    boolean isShutdown();
    
}

RunnableQueue(interface 任务队列)

package com.concurrent.customthreadpool;

/**
 * 存放提交的Runnable, 使用BlockedQueue, 设置limit
 * @author regotto
 */
public interface RunnableQueue {
   
    
    /**
     * 缓存提交到线程池中的任务
     * @param runnable
     */
    void offer(Runnable runnable);
    
    /**
     * 从缓存中获取Runnable任务
     * 如果没有任务, 调用者线程挂起, 在某些特定的时候抛出中断异常
     * @throws InterruptedException
     * @return runnable
     */
    Runnable take() throws InterruptedException;
    
    /**
     * 缓冲区大小
     * @return size
     */
    int size();
    
}

LinkedRunnableQueue(class 对RunnableQueue的封装, 用户提交任务, 线程执行任务, 此过程使用生产者-消费者模式实现)

package com.concurrent.customthreadpool;

import java.util.LinkedList;

/**
 * 线程池的内部线程队列, 缓冲区
 * @author regotto
 */
public class LinkedRunnableQueue implements RunnableQueue{
   
    
    /**
     * limit: 限制当前runnableList中还能存放多少内容
     * denyPolicy: 拒绝策略
     * runnableList: 存放runnable的缓冲区
     * threadPool: 线程池
     */
    private final int limit;
    private  final RunnableDenyPolicy denyPolicy;
    private final LinkedList<Runnable> runnableList = new LinkedList<>();
    private final ThreadPool threadPool;
    
    public LinkedRunnableQueue(int limit, RunnableDenyPolicy denyPolicy, ThreadPool threadPool){
   
        this.limit = limit;
        this.denyPolicy = denyPolicy;
        this.threadPool = threadPool;
    }
    
    @Override
    public void offer(Runnable runnable) {
   
        synchronized (runnableList) {
   
            if (runnableList.size() >= limit) {
   
           		//用户提交的任务大于限制条件, 执行对应的拒绝策略
                System.out.println(runnableList.size() + " >= " + limit + " execute deny policy");
                denyPolicy.reject(runnable, threadPool);
            } else {
   
                //添加任务到任务队列尾部, 有任务存在, 唤醒刚才wait的线程
                runnableList.addLast(runnable);
                runnableList.notifyAll();
            }
        }
    }
    
    @Override
    public Runnable take() throws InterruptedException{
   
        synchronized (runnableList) {
   
            while (runnableList.isEmpty()) {
   
                try {
   
                	//从RunnableQueue中取出任务, 如果任务为空, 使当前线程wait
                    runnableList.wait();
                } catch (InterruptedException e) {
   
         
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值