实现一个简单的线程池
2025-3-10 diaba
实现一个简单的线程池需要考虑以下几个关键点:
- 任务队列:用于存储待执行的任务。
- 工作线程:线程池中的线程,负责从任务队列中取出任务并执行。
- 任务提交:提供方法允许外部提交任务到线程池。
- 线程管理:控制线程的创建、销毁和复用。
以下是一个简单的线程池实现,支持任务的提交和执行:
import java.util.LinkedList; import java.util.Queue; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; public class SimpleThreadPool { // 线程池中的线程数量 private final int poolSize; // 任务队列 private final Queue<Runnable> taskQueue = new LinkedList<>(); // 线程池中的工作线程 private final WorkerThread[] threads; // 锁和条件变量 private final ReentrantLock lock = new ReentrantLock(); private final Condition notEmpty = lock.newCondition(); // 线程池是否关闭 private volatile boolean isShutdown = false; public SimpleThreadPool(int poolSize) { this.poolSize = poolSize; this.threads = new WorkerThread[poolSize]; // 创建并启动工作线程 for (int i = 0; i < poolSize; i++) { threads[i] = new WorkerThread(); threads[i].start(); } } // 提交任务到线程池 public void submit(Runnable task) { if (isShutdown) { throw new IllegalStateException("Thread pool is shut down."); } lock.lock(); try { taskQueue.add(task); notEmpty.signal(); // 唤醒一个等待的工作线程 } finally { lock.unlock(); } } // 关闭线程池 public void shutdown() { lock.lock(); try { isShutdown = true; notEmpty.signalAll(); // 唤醒所有等待的工作线程 } finally { lock.unlock(); } } // 工作线程类 private class WorkerThread extends Thread { @Override public void run() { while (true) { Runnable task = null; lock.lock(); try { // 检查线程池是否关闭 if (isShutdown && taskQueue.isEmpty()) { return; // 如果线程池关闭且任务队列为空,则退出线程 } // 如果任务队列为空,则等待 while (taskQueue.isEmpty() && !isShutdown) { notEmpty.await(); } // 如果线程池未关闭,则取出一个任务 if (!isShutdown) { task = taskQueue.poll(); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); } finally { lock.unlock(); } // 执行任务 if (task != null) { task.run(); } } } } }
代码解析
-
任务队列:
-
使用
LinkedList
作为任务队列,存储待执行的任务。 -
使用
ReentrantLock
和Condition
来实现线程安全的任务队列操作。
-
使用
-
工作线程:
-
每个工作线程继承自
Thread
类,重写run
方法。 - 工作线程在运行时会不断从任务队列中取出任务并执行。
-
如果任务队列为空,工作线程会调用
notEmpty.await()
进入等待状态,直到有任务被提交。
-
每个工作线程继承自
-
任务提交:
-
提供
submit
方法,允许外部提交任务到线程池。 -
提交任务时,将任务添加到任务队列,并调用
notEmpty.signal()
唤醒一个等待的工作线程。
-
提供
-
线程池关闭:
-
提供
shutdown
方法,关闭线程池。 -
设置
isShutdown
标志为true
,并调用notEmpty.signalAll()
唤醒所有等待的工作线程。 -
工作线程在检测到
isShutdown
为true
且任务队列为空时,退出运行。
-
提供
使用示例
public class Main { public static void main(String[] args) { SimpleThreadPool threadPool = new SimpleThreadPool(4); // 创建一个包含4个工作线程的线程池 // 提交任务 for (int i = 0; i < 10; i++) { int taskNumber = i; threadPool.submit(() -> { System.out.println("Executing task: " + taskNumber + " on thread: " + Thread.currentThread().getName()); try { Thread.sleep(1000); // 模拟任务执行时间 } catch (InterruptedException e) { Thread.currentThread().interrupt(); } }); } // 关闭线程池 threadPool.shutdown(); } }
输出示例
Executing task: 0 on thread: WorkerThread-0
Executing task: 1 on thread: WorkerThread-1
Executing task: 2 on thread: WorkerThread-2
Executing task: 3 on thread: WorkerThread-3
Executing task: 4 on thread: WorkerThread-0
Executing task: 5 on thread: WorkerThread-1
Executing task: 6 on thread: WorkerThread-2
Executing task: 7 on thread: WorkerThread-3
Executing task: 8 on thread: WorkerThread-0
Executing task: 9 on thread: WorkerThread-1
注意事项
-
线程安全:使用
ReentrantLock
和Condition
确保任务队列操作的线程安全。 - 优雅关闭:在关闭线程池时,确保所有任务都被执行完毕,然后让工作线程安全退出。
- 异常处理:在实际应用中,需要对任务执行中的异常进行处理,避免一个任务的失败导致整个线程池停止工作。
这个简单的线程池实现可以作为学习和理解线程池工作原理的基础。在实际项目中,建议使用Java标准库中的java.util.concurrent
包提供的线程池实现(如ExecutorService
),它们经过了严格的测试和优化,功能更加完善。
日历
个人资料

diaba 寻求合作请留言或联系mail: services@jiucaiyuan.net
链接
最新文章
存档
- 2025年3月(9)
- 2025年2月(20)
- 2025年1月(2)
- 2024年10月(1)
- 2024年8月(2)
- 2024年6月(4)
- 2024年5月(1)
- 2023年7月(1)
- 2022年10月(1)
- 2022年8月(1)
- 2022年6月(11)
- 2022年5月(6)
- 2022年4月(33)
- 2022年3月(26)
- 2021年3月(1)
- 2020年9月(2)
- 2018年8月(1)
- 2018年3月(1)
- 2017年3月(3)
- 2017年2月(6)
- 2016年12月(3)
- 2016年11月(2)
- 2016年10月(1)
- 2016年9月(3)
- 2016年8月(4)
- 2016年7月(3)
- 2016年6月(4)
- 2016年5月(7)
- 2016年4月(9)
- 2016年3月(4)
- 2016年2月(5)
- 2016年1月(17)
- 2015年12月(15)
- 2015年11月(12)
- 2015年10月(6)
- 2015年9月(11)
- 2015年8月(8)
分类
热门文章
- SpringMVC:Null ModelAndView returned to DispatcherServlet with name 'applicationContext': assuming HandlerAdapter completed request handling
- Mac-删除卸载GlobalProtect
- java.lang.SecurityException: JCE cannot authenticate the provider BC
- MyBatis-Improper inline parameter map format. Should be: #{propName,attr1=val1,attr2=val2}
- Idea之支持lombok编译
标签
最新评论
- logisqykyk
Javassist分析、编辑和创建jav... - xxedgtb
Redis—常见参数配置 - 韭菜园 ... - wdgpjxydo
SpringMVC:Null Model... - rllzzwocp
Mysql存储引擎MyISAM和Inno... - dpkgmbfjh
SpringMVC:Null Model... - tzklbzpj
SpringMVC:Null Model... - bqwrhszmo
MyBatis-Improper inl... - 乐谱吧
good非常好 - diaba
@diaba:应该说是“时间的度量依据”... - diaba
如果速度增加接近光速、等于光速、甚至大于...
最新微语
- 在每件事情上花费的东西,就是生命的一部分,而我们花费的这些东西要求立即得到回报,或者在一个长时间以后得到回报。
2025-01-23 15:46
- 诺曼·文森特说:“并不是你认为自己是什么样的人,你就是什么样的人。但是你的思想是什么样,你就是什么样的人。”
2025-01-23 15:44
- 从今天起,做一个幸福的人。喂马,砍柴,(思想)周游世界
2022-03-21 23:31
- 2022.03.02 23:37:59
2022-03-02 23:38
- 几近崩溃后,找到解决方法,总是那么豁然开朗!所以遇到问题要坚持!
2018-07-18 10:49
发表评论: