自己实现的java线程池

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

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<Thread> queue;
	private List<Thread> excutePool;
	
	@Override
	protected void init() {
		//初始化队列与执行池
		this.queue = new LinkedBlockingQueue<Thread>();
		if (null == excutePool) {
			excutePool = new ArrayList<Thread>(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<Runnable> queue;
	private List<Runnable> excutePool;
	
	private Object lock = new Object();
	@Override
	public void init() {
		//初始化队列与执行池
		this.queue = new LinkedBlockingQueue<Runnable>(queueCapacity);
		if (null == excutePool) {
			excutePool = new ArrayList<Runnable>(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<Runnable> 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();
				}
			}
			
		}

	}
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值