Java并发-实现带拒绝策略的线程池

目录

1 前言

2 线程池

 2.1 线程池的设计

2.2 阻塞队列

2.3 线程池实现

2.4 拒绝策略

2.5 完整代码


1 前言

Java多线程的学习是绕不开线程池的,线程池可以帮助我们管理线程,处理任务。在学习多线程时我已经实现过一个简单的线程池《Java并发-线程池的实现》这个这是简单的阻塞等待。

2 线程池

如下图所示:线程池最根本的应该是生产者消费者模式,生产者向线程池中提供任务,线程池中的线程进行任务消费。

 2.1 线程池的设计

在本节我们将设计一个线程池

  • 阻塞队列
  • 线程池
  • 拒绝策略
    • 阻塞等待
    • 超时等待
    • 放弃任务
    • 报错
    • 调用者线程自己执行

2.2 阻塞队列

属性

  • 队列容量
  • 真实队列
  • 锁ReentrantLock
  • 生产者的Condition
  • 消费者的Condition

take方法

  • 阻塞实现
  • 超时等待实现:是对阻塞等待的改进,可以在没有任务的时候将Worker移除,防止线程一直阻塞,有任务时候在进行创建。

put方法

  • 阻塞实现
  • 超时等待实现

tryPut方法:用于拒绝策略

{
    // 1. 队列的长度
    private int capacity;

    // 2.任务队列
    private volatile Deque<T> queue = new ArrayDeque<>();

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

    // 4.阻塞条件
    // 4.1 队列为满时,生产者进入
    private Condition fullWaitSet = lock.newCondition();
    // 4.1 队列为空时,消费者进入
    private Condition emptyWaitSet = lock.newCondition();

    public BlockQueue(int capacity) {
        this.capacity = capacity;
    }

    // 阻塞获取
    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 T take(long time, TimeUnit timeUnit) {
        lock.lock(); // 每次只能有一个线程可以消费
        try {
            long nanos = timeUnit.toNanos(time);
            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 void put(T task) {
        lock.lock();
        try {
            while (queue.size() == capacity) {
                try {
                    System.out.println("等待加入任务对列" + task);
                    fullWaitSet.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            queue.addLast(task);
            System.out.println("加入任务队列" + task);
            emptyWaitSet.signal();
        } finally {
            lock.unlock();
        }
    }

    // 超时 添加
    public boolean put(T task, long time, TimeUnit unit) {
        lock.lock();
        try {
            long nanos = unit.toNanos(time);
            while (queue.size() == capacity) {
                try {
                    if (nanos <= 0) {
                        return false;
                    }
                    System.out.println("等待加入任务队列 ..." + task);
                    nanos = fullWaitSet.awaitNanos(nanos);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            queue.addLast(task);
            System.out.println("加入任务队列 ..." + 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 {
            // 1. 队列是否满了
            if (queue.size() == capacity) {
                // 2. 实行拒绝策略
                rejectPolicy.reject(this,task);
            }else {
                // 有空闲
                queue.addLast(task);
                System.out.println("加入任务队列 ..." + task);
                emptyWaitSet.signal();
            }
        }finally {
            lock.unlock();
        }
    }
}

2.3 线程池实现

属性

  • 阻塞队列
  • 超时时间
  • 时间单位
  • 工作线程集合
  • 拒绝策略
  • 工作线程
class ThreadPool {
    private final BlockQueue<Runnable> taskQueue;

    private final int coreSize;

    private long time;

    private TimeUnit timeUnit;

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

    private RejectPolicy<Runnable> rejectPolicy;

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

    public void execute(Runnable task) {
        // 当任务数没有超过核心线程数时直接执行。
        // 当任务数超过核心线程数时候,选择拒绝策略进行执行
        synchronized (workers) {
            if (workers.size() < coreSize) {
                Worker worker = new Worker(task);
                System.out.println("新增 work" + worker);
                workers.add(worker);
                worker.start();
            } else {
                // 拒绝策略
                taskQueue.tryput(rejectPolicy,task);

            }
        }
    }

    // 真正工作的线程
    class Worker extends Thread {
        private Runnable task;

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

        @Override
        public void run() {
            // 当task不为空,执行任务
            // 当task执行完毕,再接着任务队列获取任务并执行---take会一直等待有没有新的任务。因此在没有任务时是阻塞的
            while (task != null || (task = taskQueue.take(time, timeUnit)) != null) {
                try {
                    System.out.println("正在执行..." + task);
                    task.run();
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    task = null;
                }
            }
            synchronized (workers) {
                System.out.println("当前worker使用完 被移除 " + this);
                workers.remove(this);
            }
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) {
                return true;
            }
            if (o == null || getClass() != o.getClass()) {
                return false;
            }

            Worker worker = (Worker) o;

            return task != null ? task.equals(worker.task) : worker.task == null;
        }

        @Override
        public int hashCode() {
            return task != null ? task.hashCode() : 0;
        }
    }

    public int size() {
        return taskQueue.size();
    }
}

2.4 拒绝策略

拒绝策略是一个接口,作为线程池的一个参数,在线程初始化时候确定。

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

2.5 完整代码

package cn.itcast.n6.c5;

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;

/**
 * @author : msf
 * @date : 2022/12/5
 */
public class MyThreadPool {

    public static void main(String[] args) {
        ThreadPool execuror = new ThreadPool(
                1, 1, TimeUnit.SECONDS, 1,
                (queue, task) -> {
                    // 1) 死等
                    //queue.put(task);
                    // 2) 带超时等待
                    //queue.put(task,1500,TimeUnit.MILLISECONDS);
                    // 3) 让调用者放弃任务执行 --- 什么都不写。任务没有加在队列里面,也没有尝试等待
                    // 4) 让调用者抛出异常---剩余的任务都不在执行了。
                        //throw new RuntimeException("任务执行失败" + task);
                    // 5) 让调用者自己执行任
                    task.run();
                });


        for (int i = 0; i < 3; i++) {
            int j = i;
            execuror.execute(() -> {
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "执行了" + j);
//                System.out.println(execuror.size());
            });
        }
    }
}

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


class ThreadPool {
    private final BlockQueue<Runnable> taskQueue;

    private final int coreSize;

    private long time;

    private TimeUnit timeUnit;

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

    private RejectPolicy<Runnable> rejectPolicy;

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

    public void execute(Runnable task) {
        // 当任务数没有超过核心线程数时直接执行。
        // 当任务数超过核心线程数时候,选择拒绝策略进行执行
        synchronized (workers) {
            if (workers.size() < coreSize) {
                Worker worker = new Worker(task);
                System.out.println("新增 work" + worker);
                workers.add(worker);
                worker.start();
            } else {
                // 拒绝策略
                taskQueue.tryput(rejectPolicy,task);

            }
        }
    }

    // 真正工作的线程
    class Worker extends Thread {
        private Runnable task;

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

        @Override
        public void run() {
            // 当task不为空,执行任务
            // 当task执行完毕,再接着任务队列获取任务并执行---take会一直等待有没有新的任务。因此在没有任务时是阻塞的
            while (task != null || (task = taskQueue.take(time, timeUnit)) != null) {
                try {
                    System.out.println("正在执行..." + task);
                    task.run();
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    task = null;
                }
            }
            synchronized (workers) {
                System.out.println("当前worker使用完 被移除 " + this);
                workers.remove(this);
            }
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) {
                return true;
            }
            if (o == null || getClass() != o.getClass()) {
                return false;
            }

            Worker worker = (Worker) o;

            return task != null ? task.equals(worker.task) : worker.task == null;
        }

        @Override
        public int hashCode() {
            return task != null ? task.hashCode() : 0;
        }
    }

    public int size() {
        return taskQueue.size();
    }
}

class BlockQueue<T> {
    // 1. 队列的长度
    private int capacity;

    // 2.任务队列
    private volatile Deque<T> queue = new ArrayDeque<>();

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

    // 4.阻塞条件
    // 4.1 队列为满时,生产者进入
    private Condition fullWaitSet = lock.newCondition();
    // 4.1 队列为空时,消费者进入
    private Condition emptyWaitSet = lock.newCondition();

    public BlockQueue(int capacity) {
        this.capacity = capacity;
    }

    // 阻塞获取
    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 T take(long time, TimeUnit timeUnit) {
        lock.lock(); // 每次只能有一个线程可以消费
        try {
            long nanos = timeUnit.toNanos(time);
            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 void put(T task) {
        lock.lock();
        try {
            while (queue.size() == capacity) {
                try {
                    System.out.println("等待加入任务对列" + task);
                    fullWaitSet.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            queue.addLast(task);
            System.out.println("加入任务队列" + task);
            emptyWaitSet.signal();
        } finally {
            lock.unlock();
        }
    }

    // 超时 添加
    public boolean put(T task, long time, TimeUnit unit) {
        lock.lock();
        try {
            long nanos = unit.toNanos(time);
            while (queue.size() == capacity) {
                try {
                    if (nanos <= 0) {
                        return false;
                    }
                    System.out.println("等待加入任务队列 ..." + task);
                    nanos = fullWaitSet.awaitNanos(nanos);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            queue.addLast(task);
            System.out.println("加入任务队列 ..." + 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 {
            // 1. 队列是否满了
            if (queue.size() == capacity) {
                // 2. 实行拒绝策略
                rejectPolicy.reject(this,task);
            }else {
                // 有空闲
                queue.addLast(task);
                System.out.println("加入任务队列 ..." + task);
                emptyWaitSet.signal();
            }
        }finally {
            lock.unlock();
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

兜兜转转m

一毛钱助力博主实现愿望

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值