自己动手,写一个简单的线程池(1)
来源:互联网 发布:天气软件找不到列治文 编辑:程序博客网 时间:2024/05/17 09:27
在很多场景下,创建线程并执行任务完,我们并不希望线程生命结束。因为重新创建线程的开销很大,如果能复用线程是最好不过得了。所以有了线程池就可以避免重复创建-销毁线程。
现在手写一个简单的线程池
思路
- 将执行的任务逻辑抽离,因此需要有一个任务队列
- 初始化时创建一定数量的线程,用来执行任务队列中的任务
- 当任务队列为空时,线程池中的线程等待唤醒,当有新任务加入时,唤醒线程
按照上述思路,先开始实现
首先定义好任务队列
private static final LinkedList<Runnable> TASK_QUEUE = new LinkedList<>();
并且有一个添加任务的方法
public void addTask(Runnable runnable) { synchronized (TASK_QUEUE) { TASK_QUEUE.addLast(runnable); TASK_QUEUE.notifyAll(); } }
使用同步来保证线程安全,并且在添加完后notifyAll()
来唤醒线程池中的线程。
简单起见,可以将任务队列定义为一个先进先出的队列,因此取任务时,将第一个取出。
定义一个TaskExecutor
类,继承Thread,并且重写run方法,作为执行任务的线程。
为了标记被执行任务的状态,使用一个枚举类,分别表示任务的状态
enum TaskState { FREE, RUNNING, BLOCKED, DEAD }
重新run方法
public void run() { OUTER: while (taskState != TaskState.DEAD) { Runnable runnable; synchronized (TASK_QUEUE) { while (TASK_QUEUE.isEmpty()) { try { taskState = TaskState.BLOCKED; TASK_QUEUE.wait(); } catch (InterruptedException e) { e.printStackTrace(); break OUTER; } } runnable = TASK_QUEUE.removeFirst(); } taskState = TaskState.RUNNING; runnable.run(); taskState = TaskState.FREE; } }
如果任务队列为空,则wait
,否则获取队列中的Runnable
,并执行。使用TASK_QUEUE.removeFirst()
来获取第一个元素,保证先进先出。
完整代码
public class SimpleThreadPool { private final int size; private final static int DEFAULT_SIZE = 10; private static final LinkedList<Runnable> TASK_QUEUE = new LinkedList<>(); private static final String THREAD_PREFIX = "SIMPLE_THREAD_POOL-"; private static volatile int seq = 0; private static final List<Thread> TASK_EXECUTORS = new ArrayList<>(); private static final ThreadGroup THREAD_GROUP = new ThreadGroup("Simple_Threadpool_group"); public SimpleThreadPool() { this(DEFAULT_SIZE); } public SimpleThreadPool(int size) { this.size = size; init(); } private void init() { for (int i = 0; i < size; i++) { TaskExecutor taskExecutor = createExecutor(); TASK_EXECUTORS.add(taskExecutor); taskExecutor.start(); } } public void addTask(Runnable runnable) { synchronized (TASK_QUEUE) { TASK_QUEUE.addLast(runnable); TASK_QUEUE.notifyAll(); } } private TaskExecutor createExecutor() { TaskExecutor executor = new TaskExecutor(THREAD_GROUP, THREAD_PREFIX + (seq++)); return executor; } enum TaskState { FREE, RUNNING, BLOCKED, DEAD } private class TaskExecutor extends Thread { private TaskState taskState = TaskState.FREE; private TaskExecutor(ThreadGroup threadGroup, String name) { super(threadGroup, name); } public void run() { OUTER: while (taskState != TaskState.DEAD) { Runnable runnable; synchronized (TASK_QUEUE) { while (TASK_QUEUE.isEmpty()) { try { taskState = TaskState.BLOCKED; TASK_QUEUE.wait(); } catch (InterruptedException e) { e.printStackTrace(); break OUTER; } } runnable = TASK_QUEUE.removeFirst(); } taskState = TaskState.RUNNING; runnable.run(); taskState = TaskState.FREE; } } public void shutdown() { taskState = TaskState.DEAD; } }}
测试
public class SimpleThreadPoolTest { public static void main(String[] args) { SimpleThreadPool pool = new SimpleThreadPool(); for (int i = 0; i < 40; i++) { int finalI = i; pool.addTask(() -> { System.out.println(Thread.currentThread().getName() + " ==> is execute task " + finalI); try { Thread.sleep(2_000); } catch (InterruptedException e) { e.printStackTrace(); } }); } }}
新建线程池,默认线程10个。给它40个任务
运行结果
SIMPLE_THREAD_POOL-9 ==> is execute task 0SIMPLE_THREAD_POOL-1 ==> is execute task 8SIMPLE_THREAD_POOL-8 ==> is execute task 1SIMPLE_THREAD_POOL-4 ==> is execute task 5SIMPLE_THREAD_POOL-5 ==> is execute task 4SIMPLE_THREAD_POOL-3 ==> is execute task 6SIMPLE_THREAD_POOL-7 ==> is execute task 2SIMPLE_THREAD_POOL-6 ==> is execute task 3SIMPLE_THREAD_POOL-2 ==> is execute task 7SIMPLE_THREAD_POOL-0 ==> is execute task 9SIMPLE_THREAD_POOL-1 ==> is execute task 12SIMPLE_THREAD_POOL-6 ==> is execute task 19SIMPLE_THREAD_POOL-0 ==> is execute task 18SIMPLE_THREAD_POOL-2 ==> is execute task 17SIMPLE_THREAD_POOL-7 ==> is execute task 16SIMPLE_THREAD_POOL-8 ==> is execute task 11SIMPLE_THREAD_POOL-9 ==> is execute task 10SIMPLE_THREAD_POOL-5 ==> is execute task 14SIMPLE_THREAD_POOL-3 ==> is execute task 15SIMPLE_THREAD_POOL-4 ==> is execute task 13SIMPLE_THREAD_POOL-1 ==> is execute task 20SIMPLE_THREAD_POOL-7 ==> is execute task 26SIMPLE_THREAD_POOL-0 ==> is execute task 22SIMPLE_THREAD_POOL-9 ==> is execute task 24SIMPLE_THREAD_POOL-6 ==> is execute task 21SIMPLE_THREAD_POOL-8 ==> is execute task 23SIMPLE_THREAD_POOL-2 ==> is execute task 25SIMPLE_THREAD_POOL-3 ==> is execute task 27SIMPLE_THREAD_POOL-4 ==> is execute task 29SIMPLE_THREAD_POOL-5 ==> is execute task 28SIMPLE_THREAD_POOL-0 ==> is execute task 30SIMPLE_THREAD_POOL-6 ==> is execute task 35SIMPLE_THREAD_POOL-8 ==> is execute task 34SIMPLE_THREAD_POOL-7 ==> is execute task 31SIMPLE_THREAD_POOL-9 ==> is execute task 36SIMPLE_THREAD_POOL-1 ==> is execute task 32SIMPLE_THREAD_POOL-2 ==> is execute task 33SIMPLE_THREAD_POOL-3 ==> is execute task 37SIMPLE_THREAD_POOL-5 ==> is execute task 39SIMPLE_THREAD_POOL-4 ==> is execute task 38
可以看到40个任务被SIMPLE_THREAD_POOL-0到SIMPLE_THREAD_POOL-9这10个线程执行了,一个简单的线程池就完成了
阅读全文
0 0
- 自己动手,写一个简单的线程池(1)
- 自己动手,写一个简单的线程池(2)
- 自己动手,写一个简单的线程池(3)
- 自己动手写一个简单的MVC框架(第一版)
- 自己动手写一个简单的MVC框架(第二版)
- 自己动手写一个简单的MVC框架(第二版)
- 自己动手写一个简单的bootloader
- 写一个简单的线程池
- 自己动手实现简单的线程池
- 自己动手写一个简单的Shell之一:了解Shell
- 自己动手写一个简单的Shell之二:运行程序
- 自己动手写一个简单的Shell之三:命令行解析
- 自己动手写一个简单的Shell之四:流程控制
- 自己动手写一个简单的Windows shell扩展程序
- 自己动手写一个简单的php模板引擎
- 自己动手写一个简单图片轮播的控件
- 自己动手写简单的eventbus
- ROS(二)自己动手写一个简单的发布(Publisher)、订阅(Subscriber)程序
- 谈学习
- java 原子量Atomic举例(AtomicReference )—— AtomicInteger、AtomicBoolean、AtomicLong
- 在IAR6.3上使用Jlink无法仿真控制LED,但是下载程序正常,SWO一直处于打开模式解决办法
- Java常见API-object、string、StringBuffer
- 以笔记本为工具的时间管理法(笔记)
- 自己动手,写一个简单的线程池(1)
- 配置geoDjango
- 2stackToQueue
- R语言:填色等值线图及其色标(color bar)设置
- 指针的总结好文转载
- yum常见命令
- Redis主从复制
- LeetCode基础-Stack
- django+celery+redis实现运行定时任务