java编写属于自己的线程池
什么是线程池
线程池就是以一个或多个线程[循环执行]多个应用逻辑的线程集合.
一般而言,线程池有以下几个部分:
完成主要任务的一个或多个线程.
用于调度管理的管理线程.
要求执行的任务队列.
线程池的作用:
线程池作用就是限制系统中执行线程的数量。
根据系统的环境情况,可以自动或手动设置线程数量,达到运行的最佳效果;少了浪费了系统资源,多了造成系统拥挤效率不高。用线程池控制线程数量,其他线程排队等候。一个任务执行完毕,再从队列的中取最前面的任务开始执行。若队列中没有等待进程,线程池的这一资源处于等待。当一个新任务需要运行时,如果线程池中有等待的工作线程,就可以开始运行了;否则进入等待队列。
自己实现线程池
根据如上对线程池的理解,我们自己编写一个属于自己的简单线程池:
简单的线程池接口:
publicinterfaceThreadPool{ //执行一个任务(Job),这个Job必须实现Runnable voidexecute(Jobjob); //关闭线程池 voidshutdown(); //增加工作者线程,即用来执行任务的线程 voidaddWorkers(intnum); //减少工作者线程 voidremoveWorker(intnum); //获取正在等待执行的任务数量 voidgetJobSize(); }
客户端可以通过execute(Job)方法将Job提交入线程池来执行,客户端完全不用等待Job的执行完成。除了execute(Job)方法以外,线程池接口提供了增加/减少工作者线程以及关闭线程池的方法。每个客户端提交的Job都会进入到一个工作队列中等待工作者线程的处理。
线程池接口的默认实现
publicclassDefaultThreadPoolimplementsThreadPool { //线程池维护工作者线程的最大数量 privatestaticfinalintMAX_WORKER_NUMBERS=10; //线程池维护工作者线程的默认值 privatestaticfinalintDEFAULT_WORKER_NUMBERS=5; //线程池维护工作者线程的最小数量 privatestaticfinalintMIN_WORKER_NUMBERS=1; //维护一个工作列表,里面加入客户端发起的工作 privatefinalLinkedList jobs=newLinkedList (); //工作者线程的列表 privatefinalList workers=Collections.synchronizedList(newArrayList ()); //工作者线程的数量 privateintworkerNum; //每个工作者线程编号生成 privateAtomicLongthreadNum=newAtomicLong(); //生成线程池 publicDefaultThreadPool(){ this.workerNum=DEFAULT_WORKER_NUMBERS; initializeWorkers(this.workerNum); } publicDefaultThreadPool(intnum){ if(num>MAX_WORKER_NUMBERS){ this.workerNum=DEFAULT_WORKER_NUMBERS; }else{ this.workerNum=num; } initializeWorkers(this.workerNum); } //初始化每个工作者线程 privatevoidinitializeWorkers(intnum){ for(inti=0;i MAX_WORKER_NUMBERS){ num=MAX_WORKER_NUMBERS-this.workerNum; } initializeWorkers(num); this.workerNum+=num; } } //减少工作者线程 publicvoidremoveWorker(intnum){ synchronized(jobs){ if(num>=this.workerNum){ thrownewIllegalArgumentException("超过了已有的线程数量"); } for(inti=0;i
从线程池的实现中可以看出,当客户端调用execute(Job)方法时,会不断地向任务列表jobs中添加Job,而每个工作者线程会不读的从jobs上获取Job来执行,当jobs为空时,工作者线程进入WAITING状态。当添加一个Job后,对工作队列jobs调用其notify()方法来唤醒一个工作者线程。此处我们不调用notifyAll(),避免将等待队列中的线程全部移动到阻塞队列中而造成资源浪费。
线程池的本质就是使用了一个线程安全的工作队列连接工作者线程和客户端线程。客户端线程把任务放入工作队列后便返回,而工作者线程则不端的从工作队列中取出工作并执行。当工作队列为空时,工作者线程进入WAITING状态,当有客户端发送任务过来后会通过任意一个工作者线程,随着大量任务的提交,更多的工作者线程被唤醒。
参考:《java并发编程的艺术》方腾飞