java多线程之自定义线程池
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多线程之自定义线程池的更多相关文章
- Java多线程系列--“JUC线程池”06之 Callable和Future
概要 本章介绍线程池中的Callable和Future.Callable 和 Future 简介示例和源码分析(基于JDK1.7.0_40) 转载请注明出处:http://www.cnblogs.co ...
- Java多线程系列--“JUC线程池”02之 线程池原理(一)
概要 在上一章"Java多线程系列--“JUC线程池”01之 线程池架构"中,我们了解了线程池的架构.线程池的实现类是ThreadPoolExecutor类.本章,我们通过分析Th ...
- Java多线程系列--“JUC线程池”03之 线程池原理(二)
概要 在前面一章"Java多线程系列--“JUC线程池”02之 线程池原理(一)"中介绍了线程池的数据结构,本章会通过分析线程池的源码,对线程池进行说明.内容包括:线程池示例参考代 ...
- Java多线程系列--“JUC线程池”04之 线程池原理(三)
转载请注明出处:http://www.cnblogs.com/skywang12345/p/3509960.html 本章介绍线程池的生命周期.在"Java多线程系列--“基础篇”01之 基 ...
- Java多线程系列--“JUC线程池”05之 线程池原理(四)
概要 本章介绍线程池的拒绝策略.内容包括:拒绝策略介绍拒绝策略对比和示例 转载请注明出处:http://www.cnblogs.com/skywang12345/p/3512947.html 拒绝策略 ...
- 转:java多线程CountDownLatch及线程池ThreadPoolExecutor/ExecutorService使用示例
java多线程CountDownLatch及线程池ThreadPoolExecutor/ExecutorService使用示例 1.CountDownLatch:一个同步工具类,它允许一个或多个线程一 ...
- Java多线程-新特性-线程池
Sun在Java5中,对Java线程的类库做了大量的扩展,其中线程池就是Java5的新特征之一,除了线程池之外,还有很多多线程相关的内容,为多线程的编程带来了极大便利.为了编写高效稳定可靠的多线程程序 ...
- java多线程9:线程池
线程池 线程池的优点 我们知道线程的创建和上下文的切换也是需要消耗CPU资源的,所以在多线程任务下,使用线程池的优点就有: 第一:降低资源消耗.通过重复利用已创建的线程降低线程创建和销毁造成的消耗. ...
- java多线程之 Executors线程池管理
1. 类 Executors 此类中提供的一些方法有: 1.1 public static ExecutorService newCachedThreadPool() 创建一个可根据需要创建新线程的线 ...
- Java多线程之细说线程池
前言 在认识线程池之前,我们需要使用线程就去创建一个线程,但是我们会发现有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因 ...
随机推荐
- 性能分析: 快速定位SQL问题
在数据库性能调优的实践中,SQL性能分析是至关重要的一环.一个执行效率低下的SQL语句可能会导致整个系统的性能瓶颈. 为了快速定位并解决这些问题,我们需要对SQL进行性能分析.本文将介绍一些常用的方法 ...
- json字符串转换对象或列表,多了字段不会报错
json字符串转换对象或列表,多了字段不会报错 //DEMO1 转换对象 应用 riskId public class Item { private String id; private String ...
- Luban小试牛刀
Luban小试牛刀 LubanUnity LubanUnity配置工具配置解决方案 简介 Github 文档 视频教程 Unity工具 个人感觉挺强大,便捷的,适合中大型游戏项目的配置工作.小 ...
- resttemplate调用
Map<String, Object> queryForHttp(String url, Map<String, Object> header, Map<String, ...
- 基于LoRA的RLHF
参考Github 开源模型LLM-Tuning 一.简介 (1)RLHF (基于人类反馈的强化学习) 分为三步: SFT (Supervised Fine-Tuning): 有监督的微调,使用正常的 ...
- 【换源】git命令行迁移仓库
直接git clone的话,查看本地分支,会只有默认主分支,可能是master,也可以能是设置的. 查看所有分支 git branch -a * master remotes/origin/HEAD ...
- NXP i.MX 6ULL工业核心板硬件说明书( ARM Cortex-A7,主频792MHz)
1 硬件资源 创龙科技SOM-TLIMX6U是一款基于NXP i.MX 6ULL的ARM Cortex-A7高性能低功耗处理器设计的低成本工业级核心板,主频792MHz,通过邮票孔连 ...
- Linux系统的硬件信息
查看Linux系统的硬件信息 [1]查看内核信息 uname 用于显示系统的内核信息 option -s:显示内核名称 -r:显示内核版本 [root@bogon /]# uname -a Linux ...
- SQL Server Wait Statistics监控
相关描述: https://docs.microsoft.com/en-us/sql/relational-databases/performance-monitor/sql-server-wait- ...
- 通过Docker搭建Debezium同步MySQL的数据变化
Debezium是红帽开发的一款CDC产品,和阿里的Canel类似,都是同步binlog,不过强大了一点点.为了不再麻烦,下面称之为dbz. 达拉崩吧斑得贝迪卜多比鲁翁... dbz的搭建依赖很多中间 ...