自己实现的java线程池
发布日期:2021-07-20 20:53:30 浏览次数:42 分类:技术文章

本文共 5683 字,大约阅读时间需要 18 分钟。

第一次实现的线程池(错误,有问题

import java.util.ArrayList;import java.util.List;import java.util.concurrent.LinkedBlockingQueue;public class TreadPool extends Pool{	/*	1. maxSize 	线程池允许创建的最大线程数。当workQueue使用无界队列时(如LinkBlockingQueue),则此参数无效。	它与corePoolSize的作用是调整“线程池中实际运行的线程的数量”。	例如,当新任务提交给线程池时,如果线程池中运行的线程数量小于corePoolSize,则创建新线城来处理请求;	如果此时线程池中运行的线程数量大于corePoolSize但是却小于maximumPoolSize,则仅当阻塞队列(workQueue)满时才创建新线程。	如果设置的corePoolSize等于maximumPoolSize则创建了固定大小的线程池。	如果将maximumPoolSize设置为基本的无界值(如Integer.MAX_VALUE),则允许线程池适应任意数量的并发任务	2. excute 启动	3. coreSize 核心线程数	4. keepAliveTime 当前线程池线程总数大于核心线程时,终止多余的空闲线程的时间	*/		private Integer maxSize;	private Integer coreSize;	private Integer keepAliveTime;	private LinkedBlockingQueue
queue; private List
excutePool; @Override protected void init() { //初始化队列与执行池 this.queue = new LinkedBlockingQueue
(); if (null == excutePool) { excutePool = new ArrayList
(coreSize); } //启动监控线程 new Thread(new Runnable() { @Override public void run() { checkAlive(); } }).start(); } public TreadPool(Integer maxSize, Integer coreSize, Integer keepAliveTime) { this.maxSize = maxSize; this.coreSize = coreSize; this.keepAliveTime = keepAliveTime; } //检查 每个线程是否执行完 private void checkAlive(){ while (true) { for (int i = 0; i < excutePool.size(); i++) { // 如果线程执行完毕,则移出执行池,从队列取出一个对象放入执行池 并start if (!excutePool.get(i).isAlive()) { excutePool.remove(i); Thread one = queue.poll(); if (null != one) { excutePool.add(one); one.start(); } } } try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } /** * 执行 如果执行池未满直接加入执行池并start, 否则加入等待队列 * @param target * @throws InterruptedException */ public void excute(Runnable target) throws InterruptedException { Thread thread = new Thread(target); int size = excutePool.size(); if (size==maxSize) { queue.put(thread); }else { excutePool.add(thread); thread.start(); } } }

 以上代码的问题:

    每次都创建销毁线程,浪费系统资源

    关于时间,创建线程使用是直接向系统申请资源的,这里调用系统函数进行分配资源的话耗时不好说。

    关于资源,Java线程的线程栈所占用的内存是在Java堆外的,所以是不受java程序控制的,只受系统资源限制,默认一个线程的线程栈大小是1M(当让这个可以通过设置-Xss属性设置,但是要注意栈溢出问题),但是,如果每个用户请求都新建线程的话,1024个用户光线程就占用了1个G的内存,如果系统比较大的话,一下子系统资源就不够用了,最后程序就崩溃了。
    对操作系统来说,创建一个线程的代价是十分昂贵的, 需要给它分配内存、列入调度,同时在线程切换的时候还要执行内存换页,CPU 的缓存被 清空,切换回来的时候还要重新从内存中读取信息,破坏了数据的局部性

改进后的线程池:

package com.lx.threadPool;import java.util.ArrayList;import java.util.Iterator;import java.util.List;import java.util.concurrent.LinkedBlockingQueue;public class TreadPool implements Pool{	/*	1. maxSize 	线程池允许创建的最大线程数。当workQueue使用无界队列时(如LinkBlockingQueue),则此参数无效。	它与corePoolSize的作用是调整“线程池中实际运行的线程的数量”。	例如,当新任务提交给线程池时,如果线程池中运行的线程数量小于corePoolSize,则创建新线城来处理请求;	如果此时线程池中运行的线程数量大于corePoolSize但是却小于maximumPoolSize,则仅当阻塞队列(workQueue)满时才创建新线程。	如果设置的corePoolSize等于maximumPoolSize则创建了固定大小的线程池。	如果将maximumPoolSize设置为基本的无界值(如Integer.MAX_VALUE),则允许线程池适应任意数量的并发任务	2. excute 启动	3. coreSize 核心线程数	4. keepAliveTime 当前线程池线程总数大于核心线程时,终止多余的空闲线程的时间	*/		// 最大线程数	private Integer maxSize;	// 核心线程数	private Integer coreSize;	// 空闲线程存活时间	private long keepAliveTime;	// 队列最大长度	private int queueCapacity;	private LinkedBlockingQueue
queue; private List
excutePool; private Object lock = new Object(); @Override public void init() { //初始化队列与执行池 this.queue = new LinkedBlockingQueue
(queueCapacity); if (null == excutePool) { excutePool = new ArrayList
(coreSize); } //启动监控线程 /*new Thread(new Runnable() { @Override public void run() { checkAlive(); } }).start();*/ } public TreadPool(Integer maxSize, Integer coreSize, long keepAliveTime, Integer queueCapacity) { this.maxSize = maxSize; this.coreSize = coreSize; this.keepAliveTime = keepAliveTime; this.queueCapacity = queueCapacity; init(); } /** * 这是我原来的想法 ,另开一个监控线程去取任务和让等待队列的线程开始执行. * 不能这么做, * 应该是工作线程自己取任务,无限执行,如果取不到则阻塞(queue.take()) */ //检查 每个线程是否执行完 /*private void checkAlive(){ Iterator
it = excutePool.iterator(); while (true) { while (it.hasNext()) { synchronized (lock) { // 如果线程执行完毕,则移出执行池,从队列取出一个对象放入执行池 并start if (!it.next().isAlive()) { it.remove(); Thread one ; try { one = queue.take(); //one. } catch (InterruptedException e) { System.err.println("take element exception occurred"); e.printStackTrace(); continue; } if (null != one) { excutePool.add(one); one.start(); } } } } try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } }*/ /** * 执行 如果执行池未满直接加入执行池并start, 否则加入等待队列 * @param target * @throws Exception * @throws InterruptedException */ @Override public void execute(Runnable target) throws Exception { //工作线程小于设置的核心线程, 则开启一个工作线程worker并start,循环取队列中的任务 if (excutePool.size() < coreSize) { Worker worker = new Worker(target); Thread thread = new Thread(worker); excutePool.add(worker); thread.start(); //如果工作线程大于核心线程,则直接放入队列 }else{ boolean isFull = queue.offer(target); if (!isFull) { throw new RuntimeException("Queue Rejection Exception: queue is full"); } } } class Worker implements Runnable{ private Worker(Runnable task) { boolean isFull = queue.offer(task); if (!isFull) { throw new RuntimeException("Queue Rejection Exception: queue is full"); } } @Override public void run() { while (true ) { try { //这里要用run方法(也可以让任务开始执行,不过是同步的相当于没开线程,而start是异步的), //如果用thread包装一下再start,会在工作线程外再开一个线程, 达不到管理和控制线程数的目的了 Runnable task = queue.take(); task.run(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }}

 

转载地址:https://blog.csdn.net/liao0801_123/article/details/84839365 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:mysql查看连接数show processlist
下一篇:Thread类应用,多线程

发表评论

最新留言

感谢大佬
[***.8.128.20]2024年04月20日 11时04分28秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章

基于SnowFlake算法如何让分库分表中不同的ID落在同一个库的算法的实现 2019-04-27
基于springboot的ShardingSphere5.X的分库分表的解决方案之分库解决方案(二) 2019-04-27
基于springboot的ShardingSphere5.X的分库分表的解决方案之分表解决方案(一) 2019-04-27
基于springboot的ShardingSphere5.X的分库分表的解决方案之关联查询解决方案(三) 2019-04-27
基于springboot的ShardingSphere5.X的分库分表的解决方案之基于seata的分布式事务的解决方案(十五) 2019-04-27
Linux文件管理参考 2019-04-27
FTP文件管理项目(本地云)项目日报(一) 2019-04-27
FTP文件管理项目(本地云)项目日报(二) 2019-04-27
FTP文件管理项目(本地云)项目日报(三) 2019-04-27
FTP文件管理项目(本地云)项目日报(四) 2019-04-27
【C++】勉强能看的线程池详解 2019-04-27
FTP文件管理项目(本地云)项目日报(五) 2019-04-27
FTP文件管理项目(本地云)项目日报(关于不定长包的测试) 2019-04-27
FTP文件管理项目(本地云)项目日报(六) 2019-04-27
FTP文件管理项目(本地云)项目日报(七) 2019-04-27
FTP文件管理项目(本地云)项目日报(八) 2019-04-27
【Linux】血泪教训 -- 动态链接库配置方法 2019-04-27
FTP文件管理项目(本地云)项目日报(九) 2019-04-27
以练代学设计模式 -- FTP文件管理项目 2019-04-27
FTP文件管理项目(本地云)项目日报(十) 2019-04-27