自定义线程池

自定义线程池的逻辑图:
在这里插入图片描述

步骤如下:

1.首先定义BlockingQueue,实现生产者消费者模式,设置获取、添加任务的方法
2.定义ThreadPool,设置核心数、池容量、阻塞队列对象、执行实体类等信息,实现execute方法
3、测试。

package 并发工具;

import lombok.extern.slf4j.Slf4j;

import java.util.ArrayDeque;
import java.util.Deque;
import java.util.HashSet;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

@Slf4j(topic = "c.自定义线程池")
public class 自定义线程池 {
    public static void main(String[] args) {
        ThreadPool threadPool = new ThreadPool(2,1000,TimeUnit.MILLISECONDS, 10);
        for (int i = 0; i < 5; i++) {
            int j = i;
            threadPool.execute(() -> {
                log.debug("{}",j);
            });
        }
    }
}

@FunctionalInterface    //拒绝策略
interface RejectPolicy<T>{
    void reject(BlockingQueue<T> queue,T task);
}

@Slf4j(topic = "c.ThreadPool")
class ThreadPool{
    //任务队列
    private BlockingQueue<Runnable> taskQueue;

    //线程集合
    private HashSet<Worker> workers = new HashSet<>();

    //核心线程数
    private int coreSize;

    //获取任务超时时间
    private long timeout;

    private TimeUnit timeUnit;

    private RejectPolicy<Runnable> rejectPolicy;

    //执行任务
    public void execute(Runnable task){
        //当任务没有超过coreSize时,直接交给Worker对象执行
        //如果任务数超过了CoreSize,加入任务队列暂存
        synchronized (workers) {
            if(workers.size() < coreSize){
                Worker worker = new Worker(task);
                log.debug("新增 worker {}",worker);
                workers.add(worker);
                worker.start();
            } else{
                log.debug("加入队列 {}",task);
                taskQueue.put(task);
                // 1) 死等
                // 2) 带超时等待
                // 3) 让调用者放弃任务执行
                // 4) 让调用者抛出异常
                // 5) 让调用者自己执行任务
                //taskQueue.tryPut(rejectPolicy,task);
            }
        }

    }

    public ThreadPool(int coreSize, long timeout, TimeUnit timeUnit, int queueCapacity) {
        this.coreSize = coreSize;
        this.timeout = timeout;
        this.timeUnit = timeUnit;
        this.taskQueue = new BlockingQueue<>(queueCapacity);
    }

    public ThreadPool(int coreSize, long timeout, TimeUnit timeUnit, int queueCapacity, RejectPolicy<Runnable> rejectPolicy) {
        this.coreSize = coreSize;
        this.timeout = timeout;
        this.timeUnit = timeUnit;
        this.taskQueue = new BlockingQueue<>(queueCapacity);
        this.rejectPolicy = rejectPolicy;
    }

    class Worker extends Thread{
        private Runnable task;

        public Worker(Runnable task) {
            this.task = task;
        }

        @Override
        public void run() {
            //执行任务
            // 1) 当task不为空,执行任务
            // 2) 当task执行完毕,再接着从任务队列获取任务并执行
            while( task != null || (task = taskQueue.take()) != null){
                try{
                    log.debug("正在执行....{}",task);
                    task.run();
                } catch (Exception e){
                    e.printStackTrace();
                }finally {
                    task = null;
                }
            }
            synchronized (workers){
                log.debug("work 被移除 {}",this);
                workers.remove(this);
            }
        }
    }
}


//阻塞队列
@Slf4j(topic = "c.BlockingQueue")
class BlockingQueue<T> {
    // 1. 任务队列,双向链表
    private Deque<T> queue = new ArrayDeque<>();

    // 2. 锁
    private ReentrantLock lock = new ReentrantLock();

    // 3. 生产者条件变量
    private Condition fullWaitSet = lock.newCondition();

    // 4. 消费者条件变量
    private Condition emptyWaitSet = lock.newCondition();

    // 5. 容量
    private int capcity;

    public BlockingQueue(int capcity) {
        this.capcity = capcity;
    }

    // 带超时的阻塞获取
    public T poll(long timeout, TimeUnit unit){
        lock.lock();
        try {
            //将timeout统一转换为 纳秒
            long nanos = unit.toNanos(timeout);
            while(queue.isEmpty()){
                try {
                    //返回的是剩余时间
                    if(nanos <= 0){
                        return null;
                    }
                    nanos = emptyWaitSet.awaitNanos(nanos);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            T t = queue.removeFirst();
            //唤醒等待的线程
            fullWaitSet.signal();
            return t;
        } finally {
            lock.unlock();
        }
    }

    // 阻塞获取
    public T take(){
        lock.lock();
        try {
            while(queue.isEmpty()){
                try {
                    emptyWaitSet.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            T t = queue.removeFirst();
            //唤醒等待的线程
            fullWaitSet.signal();
            return t;
        } finally {
            lock.unlock();
        }
    }

    // 阻塞添加
    public void put(T element){
        lock.lock();
        try {
            while(queue.size() == capcity){
                try {
                    fullWaitSet.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            queue.addLast(element);
            emptyWaitSet.signal();
        } finally {
            lock.unlock();
        }
    }

    // 带超时时间的阻塞添加
    public boolean offer(T task,long timeout,TimeUnit timeUnit){
        lock.lock();
        try {
            long nanos = timeUnit.toNanos(timeout);
            while(queue.size() == capcity){
                try{
                    log.debug("等待加入任务队列 {} ....",task);
                    if(nanos <= 0){
                        return false;
                    }
                    nanos = fullWaitSet.awaitNanos(nanos);
                } catch (Exception e){
                    e.printStackTrace();
                }
            }
            log.debug("加入任务队列 {}",task);
            queue.addLast(task);
            emptyWaitSet.signal();
            return true;
        } finally {
            lock.unlock();
        }
    }

    //获取大小
    public int size(){
        lock.lock();
        try{
            return queue.size();
        } finally {
            lock.unlock();
        }
    }


    public void tryPut(RejectPolicy<T> rejectPolicy, T task) {
        lock.lock();
        try{
            //判断队列是否满
            if(queue.size() == capcity){
                rejectPolicy.reject(this,task);
            } else {
                log.debug("加入任务队列 {}",task);
                queue.addLast(task);
                emptyWaitSet.signal();
            }
        } finally {
            lock.unlock();
        }
    }
}

输出:

17:37:56.216 [main] DEBUG c.ThreadPool - 新增 worker Thread[Thread-0,5,main]
17:37:56.223 [main] DEBUG c.ThreadPool - 新增 worker Thread[Thread-1,5,main]
17:37:56.223 [Thread-0] DEBUG c.ThreadPool - 正在执行....并发工具.自定义线程池$$Lambda$1/2036368507@2231df33
17:37:56.223 [main] DEBUG c.ThreadPool - 加入队列 并发工具.自定义线程池$$Lambda$1/2036368507@1f89ab83
17:37:56.224 [Thread-0] DEBUG c.自定义线程池 - 0
17:37:56.224 [Thread-1] DEBUG c.ThreadPool - 正在执行....并发工具.自定义线程池$$Lambda$1/2036368507@166b3cbc
17:37:56.224 [main] DEBUG c.ThreadPool - 加入队列 并发工具.自定义线程池$$Lambda$1/2036368507@e73f9ac
17:37:56.224 [Thread-0] DEBUG c.ThreadPool - 正在执行....并发工具.自定义线程池$$Lambda$1/2036368507@1f89ab83
17:37:56.224 [Thread-1] DEBUG c.自定义线程池 - 1
17:37:56.224 [main] DEBUG c.ThreadPool - 加入队列 并发工具.自定义线程池$$Lambda$1/2036368507@61064425
17:37:56.225 [Thread-0] DEBUG c.自定义线程池 - 2
17:37:56.225 [Thread-1] DEBUG c.ThreadPool - 正在执行....并发工具.自定义线程池$$Lambda$1/2036368507@e73f9ac
17:37:56.225 [Thread-0] DEBUG c.ThreadPool - 正在执行....并发工具.自定义线程池$$Lambda$1/2036368507@61064425
17:37:56.225 [Thread-1] DEBUG c.自定义线程池 - 3
17:37:56.225 [Thread-0] DEBUG c.自定义线程池 - 4
线程池自定义线程池工厂指的是我们可以通过自定义工厂类来创建线程池。在Java中,我们可以通过实现ThreadFactory接口来自定义线程池工厂。通过自定义工厂类,我们可以定制线程的创建方式,例如给线程设置特定的命名规则、设置线程的优先级等。 自定义线程池工厂的步骤如下: 1. 创建一个实现ThreadFactory接口的自定义工厂类,并实现其`newThread(Runnable r)`方法。 2. 在`newThread`方法中,我们可以通过`Thread`类的构造方法来创建线程,并进行一些定制化的操作,比如设置线程的名称、优先级等。 3. 自定义线程池工厂类的实例化后,我们可以将其作为参数传递给线程池创建方法中,以便使用自定义线程池工厂来创建线程池。 举个例子,假设我们需要自定义线程池工厂来创建线程池,可以按照以下步骤进行: 1. 创建一个自定义线程池工厂类,例如`CustomThreadFactory`,并实现ThreadFactory接口。 2. 在`CustomThreadFactory`类中,实现`newThread(Runnable r)`方法,并在该方法中创建线程,并设置线程的名称。 3. 在使用线程池的地方,例如`Executors.newFixedThreadPool()`方法中,将`CustomThreadFactory`类的实例传递给`newFixedThreadPool()`方法,以使用自定义线程池工厂来创建线程池。 通过自定义线程池工厂,我们可以更加灵活地控制线程的创建过程,并根据实际需求进行定制化操作。这样可以提高线程池的灵活性和可扩展性,使其更好地适用于各种场景的需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值