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. spring-boot-admin 监控

    监控单体应用 <parent> <groupId>org.springframework.boot</groupId> <artifactId>spri ...

  2. [笔记]Git常用命令大全

    Tips:当你看到这个提示的时候,说明当前的文章是由原emlog博客系统搬迁至此的,文章发布时间已过于久远,编排和内容不一定完整,还请谅解` [笔记]Git常用命令大全 日期:2018-6-16 阿珏 ...

  3. js-文件读写和上传下载的简单例子01

    现下,网络越来越快,浏览器的功能和性能越来越好,所以很多时候,已经不需要一些复杂的框架来实现不是非常复杂的功能. 我们只有在以下情况才会考虑使用框架或者现成的第三方组件: 1.功能复杂,自己写没有必要 ...

  4. ReST,以及RESTful的 简单介绍

    什么是 ReST 阮一峰说的比较清楚,具体见他的博客文章. 二.名称 ReST这个词,是[Roy Thomas Fielding](http://en.wikipedia.org/wiki/Roy_F ...

  5. 理解shell

    理解shell shell不单单是CLI,而是一种复杂的交互式程序. 1. shell的类型 当你登录系统时,系统启动什么样的shell程序取决于你的个人用户配置.在/etc/passwd文件中,用户 ...

  6. RK3568J“麒麟”+“翼辉”国产系统正式发布,“鸿蒙”也正在路上!

    RK3568J "麒麟" + "翼辉"国产系统正式发布 近期,创龙科技RK3568J全国产平台(国产化率100%,提供报告)已正式适配两大国产系统:银河麒麟嵌入 ...

  7. PHP转Go系列 | ThinkPHP与Gin框架之API接口签名设计实践

    大家好,我是码农先森. 回想起以前用模版渲染数据的岁月,那时都没有 API 接口开发的概念.PHP 服务端和前端 HTML.CSS.JS 代码混合式开发,也不分前端.后端程序员,大家都是全干工程师.随 ...

  8. 全网最适合入门的面向对象编程教程:14 类和对象的 Python 实现-类的静态方法和类方法,你分得清吗?

    全网最适合入门的面向对象编程教程:14 类和对象的 Python 实现-类的静态方法和类方法,你分得清吗? 摘要: 本文主要介绍了Python中类和对象中的类方法和静态方法,以及类方法和静态方法的定义 ...

  9. [oeasy]python0094_视频游戏_双人网球_pong_atari_mos_6502_雅达利_米洛华

    编码进化 回忆上次内容 上次 我们回顾了 微软之前的 比尔盖茨和保罗艾伦 mits 迎来的 是帮手 还是隐患? intel-8080 遇到了 mos-6502 底层硬件 驱动 游戏行业进化 不光是扑克 ...

  10. oeasy 教您玩转linux 010304 图形界面 xfce

    我们来回顾一下 上一部分我们都讲了什么? 讲了文件管理器和命令行终端互相交互 用命令nautilus在文件管理器打开某路径 这次我们来看看 图形用户界面(GUI)的情况 图形界面和发行版的关系 一个发 ...