手写一个线程池

来源:互联网 发布:数据库关系模型的概念 编辑:程序博客网 时间:2024/05/16 11:57


接口

package MyThread;import java.util.List;public interface ThreadPool {//执行一个Runnable类型的任务void execute(Runnable task);void execute(Runnable[] tasks);void execute(List<Runnable> tasks);//返回已经执行任务的个数  executor执行者 task任务int getExecuteTaskNumber();//返回任务队列的长度,即还没处理的任务个数  wait等待int getWaitTaskNumber();//返回工作线程的个数int getWorkThreadNumber();//关闭线程池void destroy();}

实现类


package MyThread;import java.util.List;import java.util.concurrent.BlockingQueue;import java.util.concurrent.LinkedBlockingDeque;import java.util.concurrent.atomic.AtomicLong;public class ThreadPoolManager implements ThreadPool {//线程池中默认的线程个数为5private static  int workerNum=5;//工作线程组WorkThread[] workThreads;//执行任务的数量 volatileprivate static volatile int executeTaskNumber=0;//任务队列,作为一个缓冲,List线程不安全(阻塞队列)private BlockingQueue<Runnable> taskQueue=new LinkedBlockingDeque<Runnable>();private static ThreadPoolManager threadPool;//可以用原子方式更新的 long 值(原子类)private AtomicLong threadNum=new AtomicLong();private ThreadPoolManager(){this(workerNum);//创建默认线程个数的线程池}private ThreadPoolManager(int worker_Num){ThreadPoolManager.workerNum=worker_Num;workThreads=new WorkThread[worker_Num];for(int i=0;i<worker_Num;i++){workThreads[i]=new WorkThread();//初始化(调用父类Thread类的无参构造方法,分配新的Thread对象)System.out.println("线程池中的工作线程数量:"+(i+1)+" 当前线程的名称是:"+workThreads[i].getName());workThreads[i].start();//一个native方法,它将启动一个新线程,并执行run()方法}}public static ThreadPool getThreadPool(){//获得默认线程个数的线程池 return getThreadPool(ThreadPoolManager.workerNum);}//单例模式public static ThreadPool getThreadPool(int worker_Num){if(worker_Num<=0){worker_Num=ThreadPoolManager.workerNum;}if(threadPool==null){threadPool=new ThreadPoolManager(worker_Num);}return threadPool;} // 执行任务,其实只是把任务加入任务队列,什么时候执行有线程池管理器觉定      public void execute(Runnable task) {          synchronized (taskQueue) {              taskQueue.add(task);              taskQueue.notifyAll();          }      }        // 批量执行任务,其实只是把任务加入任务队列,什么时候执行有线程池管理器觉定      public void execute(Runnable[] task) {          synchronized (taskQueue) {              for (Runnable t : task)                  taskQueue.add(t);              taskQueue.notifyAll();          }      }        // 批量执行任务,其实只是把任务加入任务队列,什么时候执行有线程池管理器觉定      public void execute(List<Runnable> task) {          synchronized (taskQueue) {              for (Runnable t : task)                  taskQueue.add(t);  //把任务加入队列            taskQueue.notifyAll();   //当调用execute()方法的时候,执行notiry(),只会唤醒线程池中的一个线程,注意与notoryAll()的区别        }      }  @Overridepublic int getExecuteTaskNumber() {return executeTaskNumber;}@Overridepublic int getWaitTaskNumber() {return taskQueue.size();}@Overridepublic int getWorkThreadNumber() {return workerNum;}@Overridepublic String toString() {  return "当前线程数量:" +workerNum+ " 已完成任务:"                  +executeTaskNumber+ "  等待任务数:" + getWaitTaskNumber();}@Overridepublic void destroy() {//不断检查任务队列中存在任务while (!taskQueue.isEmpty()) {// 如果还有任务没执行完成,就先睡会吧              try {                  Thread.sleep(10);              } catch (InterruptedException e) {                  e.printStackTrace();              }          }          // 工作线程停止工作,且置为null          for (int i = 0; i < workerNum; i++) {              workThreads[i].stopWorker();              workThreads[i] = null;          }          threadPool=null;          taskQueue.clear();// 清空任务队列  }/*内部类 即一个线程池对象*/private class WorkThread extends Thread{//该工作线程是否有效,用来接收该工作线程private boolean isRunnable=true;/* * 关键所在,如果任务队列不空,则求出任务执行,若任务队列为空,则等待*/@Overridepublic void run() {//接收队列当中的任务对象 任务对象Runnable类型Runnable r=null;while(isRunnable){//队列同步机制synchronized(taskQueue){while(isRunnable && taskQueue.isEmpty()){//队列为空try {taskQueue.wait(20);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}if(!taskQueue.isEmpty()){try {r=taskQueue.take();// 获取并移除第一个元素} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}if(r!=null){r.run();//执行任务}executeTaskNumber++;r=null;}}}public void stopWorker(){isRunnable=false;}}}


测试

package MyThread;public class Test {   public static void main(String[] args) {          // 创建3个线程的线程池          ThreadPool t = ThreadPoolManager.getThreadPool();          t.execute(new Runnable[] { new Task(), new Task(), new Task() });          t.execute(new Runnable[] { new Task(), new Task(), new Task() });           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++) + " 完成");          }      } }



结果:

线程池中的工作线程数量:1 当前线程的名称是:Thread-0
线程池中的工作线程数量:2 当前线程的名称是:Thread-1
线程池中的工作线程数量:3 当前线程的名称是:Thread-2
线程池中的工作线程数量:4 当前线程的名称是:Thread-3
线程池中的工作线程数量:5 当前线程的名称是:Thread-4
当前线程数量:5 已完成任务:0  等待任务数:5
任务 1 完成
任务 2 完成
任务 3 完成
任务 4 完成
任务 5 完成
任务 6 完成
当前线程数量:5 已完成任务:6  等待任务数:0


副别的贴子上的:

多线程技术主要解决处理器单元内多个线程执行的问题,它可以显著减少处理器单元的闲置时间,增加处理器单元的吞吐能力。    
    假设一个服务器完成一项任务所需时间为:T1 创建线程时间,T2 在线程中执行任务的时间,T3 销毁线程时间。

    如果:T1 + T3 远大于 T2,则可以采用线程池,以提高服务器性能。
                一个线程池包括以下四个基本组成部分:
                1、线程池管理器(ThreadPool):用于创建并管理线程池,包括 创建线程池,销毁线程池,添加新任务;
                2、工作线程(PoolWorker):线程池中线程,在没有任务时处于等待状态,可以循环的执行任务;
                3、任务接口(Task):每个任务必须实现的接口,以供工作线程调度任务的执行,它主要规定了任务的入口,任务执行完后的收尾工作,任务的执行状态等;
                4、任务队列(taskQueue):用于存放没有处理的任务。提供一种缓冲机制。
                
    线程池技术正是关注如何缩短或调整T1,T3时间的技术,从而提高服务器程序性能的。它把T1,T3分别安排在服务器程序的启动和结束的时间段或者一些空闲的时间段,这样在服务器程序处理客户请求时,不会有T1,T3的开销了。
    线程池不仅调整T1,T3产生的时间段,而且它还显著减少了创建线程的数目,看一个例子:
    假设一个服务器一天要处理50000个请求,并且每个请求需要一个单独的线程完成。在线程池中,线程数一般是固定的,所以产生线程总数不会超过线程池中线程的数目,而如果服务器不利用线程池来处理这些请求则线程总数为50000。一般线程池大小是远小于50000。所以利用线程池的服务器程序不会为了创建50000而在处理请求时浪费时间,从而提高效率。

    代码实现中并没有实现任务接口,而是把Runnable对象加入到线程池管理器(ThreadPool),然后剩下的事情就由线程池管理器(ThreadPool)来完成了