声明:
1、该篇只是提供一种自定义线程池的实现方式,可能性能、安全等方面需要优化;
2、该篇自定义线程池使用Lock(可重入锁ReentrantLock)结合Condition来实现;
3、该篇力求使用简单的方式呈现,如有错误之处,欢迎指正,在此表示感谢。
概述
自定义线程池三要素包括:
1、存储线程的容器(或叫线程池)。该容器可使用数组或链表,容器中存放执行线程,本篇使用链表实现。
2、执行线程(或叫执行器)。具体执行的线程。
3、执行任务。执行线程需要执行的具体任务。
代码
/** * 任务接口 * */ public interface Task { /** * 执行任务 */ void executeTask(); }
/** * 执行接口 * */ public interface Executor { /** * 设置任务 * * @param task 任务 */ void setTask(Task task); /** * 获取任务 * * @returnTask */ Task getTask(); /** * 启动任务 */ void startTask(); }
/** * 线程池接口 * */ public interface Pool { /** * 获取执行线程 * * @return Executor */ Executor getExecutor(); /** * 销毁线程池 */ void destory(); }
/** * 线程池实现类 * */ public class ThreadPool implements Pool { //是否开启线程池,true-开启,false-关闭 private boolean isOpen = true; //默认执行线程数量 private final static int DEFAULT_THREAD_NUM = 6; //执行线程数量,默认为DEFAULT_THREAD_NUM private static int THREAD_NUM = DEFAULT_THREAD_NUM; //存放执行线程的容器 private LinkedList<Executor> container = new LinkedList<Executor>(); //可重入锁 private Lock lock = new ReentrantLock(); //condition private Condition condition = lock.newCondition(); public ThreadPool(int threadNum){ isOpen = true; THREAD_NUM = threadNum > 0 ? threadNum : THREAD_NUM; for(int i = 0;i < THREAD_NUM;i++){ Executor executor = new ExecutorImpl(); ((ExecutorImpl)executor).setName("执行线程" + i); container.add(executor);//将执行线程加入容器中 ((ExecutorImpl)executor).start();//启动执行线程 } } public ThreadPool(){ this(DEFAULT_THREAD_NUM); } @Override public Executor getExecutor() { Executor executor = null; try{ lock.lock();//加锁 if(container.size() > 0){ executor = container.removeFirst(); }else{ condition.await();//等待,释放锁 executor = container.removeFirst(); } } catch (InterruptedException e) { e.printStackTrace(); }finally{ lock.unlock();//释放锁 } return executor; } @Override public void destory() { try{ lock.lock();//加锁 isOpen = false; condition.signalAll();//通知 container.clear(); }finally{ lock.unlock();//释放锁 } } private class ExecutorImpl extends Thread implements Executor{ //执行任务 private Task task; //可重入锁 private Lock innerLock = new ReentrantLock(); //condition private Condition innerCondition = innerLock.newCondition(); public void run(){ while(isOpen){ try{ System.out.println(Thread.currentThread().getName() + " 启动 <<<<<<<<"); innerLock.lock();;//加锁 System.out.println(Thread.currentThread().getName() + " 等待 >>>>>>>>"); innerCondition.await();//等待 } catch (InterruptedException e) { e.printStackTrace(); }finally{ innerLock.unlock();//释放锁 } System.out.println(Thread.currentThread().getName() + " 执行任务 ........"); getTask().executeTask();//执行任务 //任务执行完,放回容器中 try{ lock.lock();//加锁 //将该执行线程放回容器中 System.out.println(Thread.currentThread().getName() + " 返回容器 。。。。。。。。"); container.add(ExecutorImpl.this); System.out.println(container); condition.signalAll();//通知 }finally{ lock.unlock();//释放锁 } } } @Override public void setTask(Task task) { this.task = task; } @Override public Task getTask() { return this.task; } @Override public void startTask() { try{ innerLock.lock();//加锁 innerCondition.signal();//通知 }finally{ innerLock.unlock();//释放锁 } } } }
public class Test { public static void main(String[] args) throws InterruptedException { Pool pool = new ThreadPool(2); for(int i = 0;i < 2;i++){ Executor executor = pool.getExecutor(); Task task = new PrintTask(); executor.setTask(task); executor.startTask(); } pool.destory(); } }
执行线程0 启动 <<<<<<<<
执行线程1 启动 <<<<<<<<
执行线程1 等待 >>>>>>>>
执行线程0 等待 >>>>>>>>
执行线程0 执行任务 ........
执行线程0执行了打印任务
执行线程0 返回容器 。。。。。。。。
执行线程1 执行任务 ........
执行线程1执行了打印任务
[Thread[执行线程0,5,main]]
执行线程1 返回容器 。。。。。。。。
[Thread[执行线程0,5,], Thread[执行线程1,5,main]]