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多线程之细说线程池
前言 在认识线程池之前,我们需要使用线程就去创建一个线程,但是我们会发现有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因 ...
随机推荐
- shiro可以完成哪些工作?
shiro可以帮助我们完成:认证.授权.加密.会话管理.与Web集成.缓存等
- 关于Elasticsearch查找相关的问题汇总(match、match_phrase、query_string和term)
关于Elasticsearch查找相关的问题汇总(match.match_phrase.query_string和term) 查询全部: { "query": { "ma ...
- idea部署运行tomcat项目方法
在导航栏点击Add Configuration-或者(打开菜单Run->Edit Configuration) 点击+号,选择Tomcat Server ->选择Local->在Na ...
- openfly:基于nginx的4层代理管理平台
简介 作者:京城郭少 基于nginx的4层代理管理平台 支持的功能: 被动健康检查 白名单 include导入文件 哈希 backup冗余互备 weight权重 注释 ...... 部署openfly ...
- Git配置环境变量
由于学习需要装了git,使用终端查看版本号时 提示 'git' 不是内部或外部命令,也不是可运行的程序 或批处理文件. 原因 因为没有配置Git环境变量 解决方法:配置环境变量 开始菜单=>设置 ...
- 实验6.交换机MAC地址表简单实验
# 实验6.交换机Mac地址表 本实验用于验证和测试交换机的Mac地址表的特性. 实验组 测试 测试在PC1没有pingPC2时,此时mac表为空 当PC1ping一个其他的ip而不是PC2时,无论是 ...
- ODPS 不用循环生成连续日期
生成 20230801 ~ 20230831之间的每一天的sql代码怎么写? 只要一行代码. 一行代码: select TO_CHAR(DATEADD(TO_DATE(bizdate,'yyyymmd ...
- Linux OpenGrok搭建
目录 一.目的 二.环境 三.相关概念 3.1 OpenGrok 3.2 CTags 3.3 Tomcat 四.OpenGrok搭建 4.1 安装jdk 4.2 安装ctags依赖 4.3 安装uni ...
- 【基础计算】ESDF栅格距离图计算并行加速版
前言与参考 这一部分仅为路径规划源码及论文GPIR的一个小部分,但是有代码实现,第一次看的时候有些懵,所以特此记录:主要是设置好了栅格地图后,添加了障碍物后,对其的欧式距离计算和梯度计算等.原代码中为 ...
- nginx配置端口转发 并修改swagger路径配置
项目服务器为linux,仅开放特定外网端口 所以部署的docker服务需要通过nginx 做端口转发 这里的配置使用的是 nginx docker服务 配置步骤: 1. 修改nginx配置文件,我这里 ...