1.背景

线程池.....大家常用....

自己搞一个,顺便练习一下多线程编程

2.自定义线程代码

2.1.拒绝策略接口

@FunctionalInterface
public interface MyRejectPolicy<T> {
void reject(MyBlockingQueue<T> queue, T task);
}

2.2.自定义阻塞队列

@Slf4j
public class MyBlockingQueue<T> {
// 1.任务队列
private Deque<T> queue = new ArrayDeque<>();
// 2.容量
private int capacity;
// 3.锁
private ReentrantLock lock = new ReentrantLock();
// 4.生产者条件变量
private Condition producerCondition = lock.newCondition();
// 5.消费者条件变量
private Condition consumerCondition = lock.newCondition(); // 构造方法
public MyBlockingQueue(int capacity) {
this.capacity = capacity;
} // 阻塞获取
public T take() {
lock.lock();
try {
// 判断是否为空
while (queue.isEmpty()) {
try {
// 无任务消费者等待
log.info("无任务,消费者等待....");
consumerCondition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 不为空,消费者获取一个任务
T t = queue.removeFirst();
log.info("消费者已获取到任务t={}", t);
// 通知生产者放入任务
producerCondition.signal();
return t;
} finally {
lock.unlock();
}
} // 阻塞添加
public void put(T t) {
lock.lock();
try {
while (queue.size() >= capacity) {
try {
// 队列已满,生产者等待
log.info("......队列已满,生产者等待");
producerCondition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 放入队列
queue.addLast(t);
log.info("......生产者,以将任务放入队列");
// 通知消费者获取任务
consumerCondition.signal();
} finally {
lock.unlock();
}
}
}

2.3.自定义工作线程

@Slf4j
public class MyWorkerThread extends Thread {
// 线程集合
private HashSet<MyWorkerThread> workerThreadList = new HashSet<>();
// 任务队列
private MyBlockingQueue<Runnable> taskQueue;
// 任务对象
private Runnable task; /**
* 构造方法
*
* @param task
*/
public MyWorkerThread(HashSet<MyWorkerThread> workerThreadList, MyBlockingQueue<Runnable> taskQueue, Runnable task) {
this.workerThreadList = workerThreadList;
this.taskQueue = taskQueue;
this.task = task;
} /**
* 执行任务
*/
@Override
public void run() {
// 当【task不为空】时执行当前任务
// 当【task为空】时,从队列中获取任务再执行
while (task != null || ((task = taskQueue.take()) != null)) {
try {
// 执行任务
log.info("执行当前任务:{}", task);
task.run();
} finally {
// 将任务设置为空
task = null;
}
}
// 无任务,释放线程
synchronized (workerThreadList) {
log.info("无任务,删除当前线程:{}", this);
workerThreadList.remove(this);
}
}
}

2.4.自定义线程池

@Slf4j
public class MyThreadPool {
// 核心线程数
private int coreSize;
// 阻塞队列
private MyBlockingQueue<Runnable> taskQueue;
// 线程集合
private HashSet<MyWorkerThread> workerThreadList = new HashSet<>();
// 拒绝策略
private MyRejectPolicy<Runnable> rejectPolicy; /**
* 线程池构造器
*
* @param coreSize
* @param rejectPolicy
*/
public MyThreadPool(int coreSize, MyRejectPolicy<Runnable> rejectPolicy) {
this.coreSize = coreSize;
this.taskQueue = new MyBlockingQueue<>(coreSize);
this.rejectPolicy = rejectPolicy;
} /**
*
*/
public void execute(Runnable task) {
// 当任务数【没有超过】核心线程数coreSize时,直接给workerThreadList 执行
// 当任务数【超过】核心线程数coreSize时,放入队列
synchronized (workerThreadList) {
int size = workerThreadList.size();
if (size < coreSize) {
MyWorkerThread workerThread = new MyWorkerThread(workerThreadList, taskQueue, task);
workerThread.setName("工作线程-" + (size + 1));
log.info("创建线程对象:{},执行任务:{}", workerThread, task);
workerThreadList.add(workerThread);
workerThread.start();
} else {
taskQueue.put(task);
}
}
}
}

3.测试

@Slf4j
public class Test01 {
/**
* 测试自定义的线程池
* @param args
*/
public static void main(String[] args) {
// 创建线程池
MyThreadPool pool = new MyThreadPool(2, (queue, task) -> {
queue.put(task);
});
// 执行任务
pool.execute(()->{
log.info("执行任务1...");
});
pool.execute(()->{
log.info("执行任务2...");
});
pool.execute(()->{
log.info("执行任务3...");
});
}
}

完美!

java多线程之自定义线程池的更多相关文章

  1. Java多线程系列--“JUC线程池”06之 Callable和Future

    概要 本章介绍线程池中的Callable和Future.Callable 和 Future 简介示例和源码分析(基于JDK1.7.0_40) 转载请注明出处:http://www.cnblogs.co ...

  2. Java多线程系列--“JUC线程池”02之 线程池原理(一)

    概要 在上一章"Java多线程系列--“JUC线程池”01之 线程池架构"中,我们了解了线程池的架构.线程池的实现类是ThreadPoolExecutor类.本章,我们通过分析Th ...

  3. Java多线程系列--“JUC线程池”03之 线程池原理(二)

    概要 在前面一章"Java多线程系列--“JUC线程池”02之 线程池原理(一)"中介绍了线程池的数据结构,本章会通过分析线程池的源码,对线程池进行说明.内容包括:线程池示例参考代 ...

  4. Java多线程系列--“JUC线程池”04之 线程池原理(三)

    转载请注明出处:http://www.cnblogs.com/skywang12345/p/3509960.html 本章介绍线程池的生命周期.在"Java多线程系列--“基础篇”01之 基 ...

  5. Java多线程系列--“JUC线程池”05之 线程池原理(四)

    概要 本章介绍线程池的拒绝策略.内容包括:拒绝策略介绍拒绝策略对比和示例 转载请注明出处:http://www.cnblogs.com/skywang12345/p/3512947.html 拒绝策略 ...

  6. 转:java多线程CountDownLatch及线程池ThreadPoolExecutor/ExecutorService使用示例

    java多线程CountDownLatch及线程池ThreadPoolExecutor/ExecutorService使用示例 1.CountDownLatch:一个同步工具类,它允许一个或多个线程一 ...

  7. Java多线程-新特性-线程池

    Sun在Java5中,对Java线程的类库做了大量的扩展,其中线程池就是Java5的新特征之一,除了线程池之外,还有很多多线程相关的内容,为多线程的编程带来了极大便利.为了编写高效稳定可靠的多线程程序 ...

  8. java多线程9:线程池

    线程池 线程池的优点 我们知道线程的创建和上下文的切换也是需要消耗CPU资源的,所以在多线程任务下,使用线程池的优点就有: 第一:降低资源消耗.通过重复利用已创建的线程降低线程创建和销毁造成的消耗. ...

  9. java多线程之 Executors线程池管理

    1. 类 Executors 此类中提供的一些方法有: 1.1 public static ExecutorService newCachedThreadPool() 创建一个可根据需要创建新线程的线 ...

  10. Java多线程之细说线程池

    前言 在认识线程池之前,我们需要使用线程就去创建一个线程,但是我们会发现有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因 ...

随机推荐

  1. RAS非对称加解密-RAS加解密和签名和验签,密钥生成器(java代码)

    RAS非对称加解密-RAS加解密和签名和验签,密钥生成器(java代码)RSA 算法是一种非对称加解密算法.服务方生成一对 RSA 密钥,即公钥 + 私钥,将公钥提供给调用方,调用方使用公钥对数据进行 ...

  2. python根据模板文件批量创建文件脚本

    1.模板文件.txt 欢迎访问这座城市:德州行政区域编号:371400根据高德地图(https://lbs.amap.com/tools/picker)查询经纬度查询: jingdu,weiduBYE ...

  3. mybatis sqlmap sql in 查询

    <select id="selectBlogs" parameterType="map"> SELECT * FROM blog WHERE use ...

  4. 这个vue3的后台管理系统虽然简洁但不简单

    今天介绍一个新的Vue后台管理框架,相比其他后台功能丰富管理系统,这个后台管理系统可以用干净简洁来形容--Nova-admin Nova-admin Nova-admin 是一个基于Vue3.Vite ...

  5. golang执行命令 && 实时获取输出结果

    背景 golang可以获取命令执行的输出结果,但要执行完才能够获取. 如果执行的命令是ssh,我们要实时获取,并执行相应的操作呢? 示例 func main() { user := "roo ...

  6. .NET 日志系统-3 结构化日志和集中日志服务

    .NET 日志系统-3 结构化日志和集中日志服务 系列文章 认识.NET 日志系统 https://www.cnblogs.com/ZYPLJ/p/17663487.html .NET 认识日志系统- ...

  7. 全国产T3+FPGA的SPI与I2C通信方案分享

    近年来,随着中国新基建.中国制造2025规划的持续推进,单ARM处理器越来越难胜任工业现场的功能要求,特别是如今能源电力.工业控制.智慧医疗等行业,往往更需要ARM + FPGA架构的处理器平台来实现 ...

  8. mirai Bot初始化配置

    RT 其实本来我的bot已经因为自己手贱登陆qq nt直接报废了,但是论坛里有佬提供了新的协议库,那这不赶紧复活bot都对不起这个新的协议库. 本文写于2024年7月4日19:20:21,可能随着时间 ...

  9. 基于SSD202D芯片的最小嵌入式Linux开发板来了 仅需99元 入门嵌入式Linux必选

  10. 松灵机器人scout mini小车 自主导航(2)——仿真指南

    松灵机器人Scout mini小车仿真指南 之前介绍了如何通过CAN TO USB串口实现用键盘控制小车移动.但是一直用小车测试缺乏安全性.而松灵官方贴心的为我们准备了gazebo仿真环境,提供了完整 ...