代码:
接口类
package ThreadPool;
public interface ITaskInterface
{
public void star();
}
线程池实现
package ThreadPool; import java.util.LinkedList; import java.util.List; /** * 线程池类,线程管理器:创建线程,执行任务,销毁线程,获取线程基本信息 */ public final class ThreadPool { // 线程池中默认线程的个数为5 private static int worker_num = 5; // 工作线程 private WorkThread[] workThrads; // 未处理的任务 private static volatile int finished_task = 0; // 任务队列,作为一个缓冲,List线程不安全 // private List<Runnable> taskQueue = new LinkedList<Runnable>(); private List<ITaskInterface> taskQueue = new LinkedList<ITaskInterface>(); private static ThreadPool threadPool; // 创建具有默认线程个数的线程池 private ThreadPool() { this(5); } // 创建线程池,worker_num为线程池中工作线程的个数 private ThreadPool(int worker_num) { ThreadPool.worker_num = worker_num; workThrads = new WorkThread[worker_num]; for (int i = 0; i < worker_num; i++) { workThrads[i] = new WorkThread(); workThrads[i].start();// 开启线程池中的线程 } } // 单态模式,获得一个默认线程个数的线程池 public static ThreadPool getThreadPool() { return getThreadPool(ThreadPool.worker_num); } // 单态模式,获得一个指定线程个数的线程池,worker_num(>0)为线程池中工作线程的个数 // worker_num<=0创建默认的工作线程个数 public static ThreadPool getThreadPool(int worker_num1) { if (worker_num1 <= 0) worker_num1 = ThreadPool.worker_num; if (threadPool == null) threadPool = new ThreadPool(worker_num1); return threadPool; } // 执行任务,其实只是把任务加入任务队列,什么时候执行有线程池管理器觉定 public void execute(ITaskInterface task) { synchronized (taskQueue) { taskQueue.add(task); taskQueue.notify(); } } // 批量执行任务,其实只是把任务加入任务队列,什么时候执行有线程池管理器觉定 public void execute(ITaskInterface[] task) { synchronized (taskQueue) { for (ITaskInterface t : task) taskQueue.add(t); taskQueue.notify(); } } // 批量执行任务,其实只是把任务加入任务队列,什么时候执行有线程池管理器觉定 public void execute(List<ITaskInterface> task) { synchronized (taskQueue) { for (ITaskInterface t : task) taskQueue.add(t); taskQueue.notify(); } } // 销毁线程池,该方法保证在所有任务都完成的情况下才销毁所有线程,否则等待任务完成才销毁 public void destroy() { while (!taskQueue.isEmpty()) {// 如果还有任务没执行完成,就先睡会吧 try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } } // 工作线程停止工作,且置为null for (int i = 0; i < worker_num; i++) { workThrads[i].stopWorker(); workThrads[i] = null; } threadPool=null; taskQueue.clear();// 清空任务队列 } // 返回工作线程的个数 public int getWorkThreadNumber() { return worker_num; } // 返回已完成任务的个数,这里的已完成是只出了任务队列的任务个数,可能该任务并没有实际执行完成 public int getFinishedTasknumber() { return finished_task; } // 返回任务队列的长度,即还没处理的任务个数 public int getWaitTasknumber() { return taskQueue.size(); } // 覆盖toString方法,返回线程池信息:工作线程个数和已完成任务个数 @Override public String toString() { return "WorkThread number:" + worker_num + " finished task number:" + finished_task + " wait task number:" + getWaitTasknumber(); } /** * 内部类,工作线程 */ private class WorkThread extends Thread { // 该工作线程是否有效,用于结束该工作线程 private boolean isRunning = true; /* * 关键所在啊,如果任务队列不空,则取出任务执行,若任务队列空,则等待 */ @Override public void run() { ITaskInterface r = null; while (isRunning) {// 注意,若线程无效则自然结束run方法,该线程就没用了 synchronized (taskQueue) { while (isRunning && taskQueue.isEmpty()) {// 队列为空 try { taskQueue.wait(20); } catch (InterruptedException e) { e.printStackTrace(); } } if (!taskQueue.isEmpty()) r = taskQueue.remove(0);// 取出任务 } if (r != null) { r.star();// 执行任务 } finished_task++; r = null; } } // 停止工作,让该线程自然执行完run方法,自然结束 public void stopWorker() { isRunning = false; } } }
测试类
package ThreadPool; public class TestThreadPool { public static void main(String[] args) { // 创建3个线程的线程池 ThreadPool t = ThreadPool.getThreadPool(3); t.execute(new ITaskInterface[] { new Task(), new Task(), new Task() }); t.execute(new ITaskInterface[] { new Task(), new Task(), new Task() }); System.out.println(t); t.destroy();// 所有线程都执行完成才destory System.out.println(t); } // 任务类 static class Task implements ITaskInterface { private static volatile int i = 1; public void star() { System.out.println("由旁边发布的任务 " + (i++) + "已经完成"); } } }
注:此段代码是基于csdn上的一位网友的代码然后自己做了修改,为了说明问题没有重新写。
以下是要说明的问题:
首先看被绿色标注的代码,线程池是在初始化是就启动多个线程,然后在线程中的run()方法中用一个while循环去不断的轮询任务队列,如果有任务就执行,没有任务就wait
若有任务添加进任务队列,就唤醒线程。
再看红色部分,这是一个接口,在许多线程池的实现中使用的都是runnable接口,但是这个实现的接口可以自己定义,而且在线程池中的线程在run()方法中执行的任务中的方法也只是一个普通的方法,没有什么特别,(众所周知,一个类实现了runnable接口,但是没有使用start()方法来启动线程则在执行run()方法时这只是一个普通的方法)完全可以替换成一个你自己定义的接口。
为什么要定义接口,因为在线程池中的线程中需要知道怎么来执行任务类中的任务,所以需要定义一个接口来让线程通过定义接口变量来调用接口中的方法,这个方法对于线程来说是已知的。