Java线程池的实现
线程池的作用:
一个线程的周期分为:创建、运行、销毁三个阶段。
处理一个任务时,首先创建一个任务线程,然后执行任务,完了还要销毁线程。而线程只有处于运行状态的时候,才是真的在处理我们交给它的任务,这个阶段才是有效运行时间。
所以,我们希望花在创建和销毁线程的资源越少越好。如果不销毁线程,而这个线程又不能被其他的任务调用,那么就会出现资源的浪费。为了提高效率,减少创建和销毁线程带来时间和空间上的浪费,出现了线程池技术。这种技术是在开始就创建一定量的线程,批量处理一类任务,等待任务的到来。任务执行完毕后,线程又可以执行其他的任务。等不再需要线程的时候,就销毁。这样就省去了频繁创建和销毁线程的麻烦。
1. 线程池类
import java.util.LinkedList; import java.util.List; public class MyThreadPool { // 线程池中默认线程的个数为5个 private static int worker_num = 5; // 工作的线程 private WorkThread[] workThreads; // 未处理的任务 private static volatile int finished_task = 0; // 任务队列,作为一个缓冲,List线程不安全所以需要在使用的过程中对它进行同步。 private List<Runnable> taskQueue = new LinkedList<Runnable>(); // 单例模式 private static MyThreadPool threadPool; // 私有化构造方法 private MyThreadPool(){ this(5); } // 创建线程池,num为线程池工作线程的个数 private MyThreadPool(int num) { MyThreadPool.worker_num = num; workThreads = new WorkThread[num]; for (int i = 0; i < num; i++) { workThreads[i] = new WorkThread(); workThreads[i].start(); } } // 获得一个线程池,默认线程数 public static MyThreadPool getThreadPool(){ return getThreadPool(MyThreadPool.worker_num); } // 单例模式,获得一个线程池 public static MyThreadPool getThreadPool(int num) { if(num <= 0){ num = MyThreadPool.worker_num; } if(threadPool == null){ synchronized(MyThreadPool.class){ if(threadPool == null) threadPool = new MyThreadPool(num); } } return threadPool; } /** * 执行任务 * 将该任务加入到任务队列的末尾,等待工作线程的调度 * @param task */ public void execute(Runnable task){ synchronized (taskQueue){ taskQueue.add(task); taskQueue.notify(); } } /** * 批量执行任务 * 将任务放到任务队列的末尾,等待工作线程的调度 * @param task */ public void execute(Runnable[] task){ synchronized (taskQueue){ for (Runnable runnable : task) { taskQueue.add(runnable); } taskQueue.notify(); } } /** * 批量执行任务 * 将任务放到任务队列的末尾,等待工作线程的调度 * @param task */ public void execute(List<Runnable> task){ synchronized (taskQueue){ for (Runnable runnable : task) { taskQueue.add(runnable); } taskQueue.notify(); } } /** * 销毁线程池 * 在所有任务都完成的情况下才销毁所有线程,否则等待任务队列的任务全部完成才销毁 */ public void destroy(){ while(!taskQueue.isEmpty()){// 如果还有任务没执行完成,就等会再看看 try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } } // 工作线程停止工作,且置为null for (int i = 0; i < MyThreadPool.worker_num; i++) { workThreads[i].stopWorker(); workThreads[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(); } /** * 内部类,工作线程用来执行任务线程 * @author liu * */ private class WorkThread extends Thread{ // 该工作线程是否有效,用于自然结束该工作线程 private boolean isRunning = true; /* * 工作线程的关键之处,如果任务队列不空,则取出任务执行,若任务队列空,则等待。直到任务队列有任务时才取出执行 */ @Override public void run() { Runnable r = null; while( isRunning ){// 队列为空 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.run(); // 完成的任务加一 finished_task += 1; } r = null; } } // 停止工作,让该线程自然执行完run方法,自然结束 public void stopWorker() { this.isRunning = false; } } }
2. 测试代码
public class TestThreadPool { public static void main(String[] args) { // 创建5个线程的线程池 MyThreadPool t = MyThreadPool.getThreadPool(5); Runnable[] r = new Runnable[] { new Task(), new Task(), new Task()}; t.execute(r); r = new Runnable[] {new Task(), new Task(), new Task()}; t.execute(r); System.out.println(t); t.destroy();// 所有线程都执行完成才destory System.out.println(t); } // 任务类 static class Task implements Runnable { private static volatile int i = 1; @Override public void run() {// 执行任务 System.out.println("任务 " + (i++) + " 完成"); } } }
3. 运行结果
注:参照网上的代码和思路,通过自己的修改和调试完成