线程池就好像...
一个工厂从外面接业务(任务)回来,而它养了一定数量的工人,工人主动去领取任务,然后负责这个任务的实施。
然而这个工厂怎么管理好业务和工人,怎么管理好任务的分配而不发生错误,即需要一个良好的机制了。
回到线程池,一样的道理。
有以下几个基本点:(这里针对简单基础的情况)
1. 用一个队列管理任务,任务包括创建时间、提交时间、执行时间、结束时间等描述任务执行过程的属性。(就好像一个工程项目做的施工计划或者合同计划类似属性)
2.用一个队列管理工作线程(工人),工作线程主动到线程任务队列中拿任务,如果队列为空则等待,直到有任务进来然后唤醒他们——有活干了!
3.有一个后台线程(监理)负责监控这些工作线程的工作状态,是空闲还是忙碌。
4.任务接口(或则抽象类),所有执行的任务必须符合标准。(就好像一个公司大部分只做相关业务的单子,除了......)
下面给出代码了,也是参考了网上的,进行了适当的调整,并且给出了适当的注释!
1.task接口。
package com.fox.threadPool; import java.util.Date; /** * @author huangfox * 抽象类 * 任务的基类,所有任务必须继承这个类。 * 任务的具体业务代码在core()方法中执行。 */ public abstract class Task implements Runnable { //任务创建时间 private Date createT = null; //提交执行时间 private Date submitT = null; //开始执行时间 private Date runingT = null; //结束执行时间 private Date finishT = null; //任务编号 private int taskID ; //构造 public Task(){ this.createT = new Date(); } @Override public void run() { core(); } //核心业务代码,即任务的主要工作。 public abstract void core(); //任务详细信息 public void display(){ System.out.println("/t任务标示:" + this.taskID + ";/t创建时间:" + this.createT + ";/t提交时间:" + this.submitT + ";/t开始执行时间:" + this.runingT + ";/t结束执行的时间:" + this.finishT ); } public Date getCreateT() { return createT; } public void setCreateT(Date createT) { this.createT = createT; } public Date getSubmitT() { return submitT; } public void setSubmitT(Date submitT) { this.submitT = submitT; } public Date getRuningT() { return runingT; } public void setRuningT(Date runingT) { this.runingT = runingT; } public Date getFinishT() { return finishT; } public void setFinishT(Date finishT) { this.finishT = finishT; } public int getTaskID() { return taskID; } public void setTaskID(int taskID) { this.taskID = taskID; } }
2.worker——工作线程
package com.fox.threadPool; /** * @author huangfox * 驱动任务的线程类。 * 由线程池统一管理。 */ public class Worker extends Thread { //是否可运行 private boolean isRunning = true; //等待任务中(尚未驱动任务),当接收到任务并执行后isWating=false。 private boolean isWaiting = true; //线程的标示 private int id = -1; //构造 public Worker(int id){ this.id = id; start(); } //停止当前线程 public void Stop(){ this.isRunning = false; } //获得isRunning的状态 public boolean getIsRunning(){ return this.isRunning; } //获得isWating的状态 public boolean getIsWaiting(){ return this.isWaiting; } @Override public void run() { //循环执行任务队列中的任务,前提是当前线程是可运行的,即isRunning=true while(isRunning){ //声明一个任务 Task task = null; //从任务队列中取出一个任务 synchronized (ThreadPool.getTasks()) { //如果任务队列为空,则让任务队列等待一段时间再看看是否有任务可执行。 while(ThreadPool.isTaskEmp()){ try { ThreadPool.getTasks().wait(10); } catch (InterruptedException e) { e.printStackTrace(); } } //当上面的循环执行结束,则说明任务队列不为空 //取出第一个任务进行执行 task = ThreadPool.getTasks().remove(0); } if( task != null ){ //当任务为可执行任务时(not null),则这个线程有任务要处理了,则他的状态就不是闲置了。 this.isWaiting = false; //执行任务 task.run(); } //任务执行结束 //重新置回当前线程的状态为闲置 this.isWaiting = true; ThreadPool.getTasks().remove(task); task = null ; }// end synchronized } }
3.ThreadPool——线程池
package com.fox.threadPool; import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.List; /** * @author huangfox * 线程池,线程管理类 */ public class ThreadPool { //线程池实例 private static ThreadPool pool = ThreadPool.getInstance(); //线程池中线程数量 private int MAX_THREAD_COUNT = 10; //线程数组 private static Worker[] workers ; //任务队列 private static List<Task> tasks = Collections.synchronizedList(new ArrayList<Task>()); //任务标示 private static int taskid = 0; // public static List<Task> getTasks() { return tasks; } //单例 public static synchronized ThreadPool getInstance(){ if(pool == null){ return new ThreadPool(); }else{ return pool; } } //构造 private ThreadPool(){ this.workers = new Worker[MAX_THREAD_COUNT]; for (int i = 0; i < this.workers.length; i++) { this.workers[i] = new Worker(i); } } //构造(重载) // private ThreadPool(int maxThreadCount){ // this.MAX_THREAD_COUNT = maxThreadCount; // this.workers = new Worker[maxThreadCount]; // for (int i = 0; i < maxThreadCount; i++) { // this.workers[i] = new Worker(i); // } // } //销毁线程池 public synchronized void destory(){ for (int i = 0; i < this.workers.length; i++) { //这里不是线程的stop方法。 this.workers[i].Stop(); //清除线程 this.workers[i] = null; } //清除任务队列。 this.tasks.clear(); } //获得任务队列是否为空 public static boolean isTaskEmp(){ return tasks.isEmpty(); } //获得当前线程池的情况 public void display(){ System.out.println("线程池情况:"); for (int i = 0; i < this.workers.length; i++) { System.out.println("/t"+this.workers[i].getId() + "/t" + (this.workers[i].getIsWaiting()==true?"闲置":"工作")); } } //添加单个任务 public void addTask(Task newTask){ synchronized (this.tasks) { //设定任务标示 newTask.setTaskID(++this.taskid); //设定任务提交时间 newTask.setSubmitT(new Date()); //将任务加入到任务队列当中 this.tasks.add(newTask); // System.out.print("添加任务:" ); // newTask.display(); //唤醒任务队列,因为在线程取任务的时候若任务队列为空则会将tasks.wait(); //这里需要唤醒。 this.tasks.notifyAll(); } } }
4.monitor——监控类
package com.fox.threadPool; /** * @author huangfox * */ public class Monitor extends Thread { ThreadPool pool = null ; public Monitor(ThreadPool p){ this.pool = p ; } @Override public void run() { while(true){ pool.display(); try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
5.以下是配合测试的,具体的任务TaskTest
package com.fox.threadPool; /** * @author huangfox * 简单实现一个任务类。 */ public class TaskTest extends Task { @Override public void core() { System.out.println("任务【" + super.getTaskID() + "】开始..."); try { //模拟具体业务运行时间 Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("任务【" + super.getTaskID() + "】结束..."); } }
6.测试主程序
package com.fox.threadPool; public class MainApp { /** * @param args */ public static void main(String[] args) { ThreadPool pool = ThreadPool.getInstance(); // Monitor m = new Monitor(pool); m.setDaemon(true); m.start(); for (int i = 0; i < 10; i++) { pool.addTask(new TaskTest()); try { //控制添加任务的速度。 Thread.sleep(150); } catch (InterruptedException e) { e.printStackTrace(); } } } }
虽然是入门级的线程池,但是基本的原理还是比较清晰地。