线程池是一种多线程处理形式,处理过程中将任务加入到队列,然后在创建线程后自己主动启动这些任务。线程池线程都是后台线程。每一个线程都使用默认的堆栈大小,以默认的优先级执行。并处于多线程单元中。

假设某个线程在托管代码中空暇(如正在等待某个事件),则线程池将插入还有一个辅助线程来使全部处理器保持繁忙。

假设全部线程池线程都始终保持繁忙,但队列中包括挂起的工作,则线程池将在一段时间后创建还有一个辅助线程但线程的数目永远不会超过最大值。超过最大值的线程能够排队,但他们要等到其它线程完毕后才启动。

组成部分

1、线程池管理器(ThreadPoolManager):用于创建并管理线程池
2、工作线程(WorkThread): 线程池中线程
3、任务接口(Task):每一个任务必须实现的接口。以供工作线程调度任务的运行。

4、任务队列:用于存放没有处理的任务。提供一种缓冲机制。

技术背景编辑

在面向对象编程中,创建和销毁对象是非常费时间的,由于创建一个对象要获取内存资源或者其他很多其他资源。在Java中更是如此,虚拟机将试图跟踪每个对象。以便可以在对象销毁后进行垃圾回收。所以提高服务程序效率的一个手段就是尽可能降低创建和销毁对象的次数,特别是一些非常耗资源的对象创建和销毁。

怎样利用已有对象来服务就是一个须要解决的关键问题,事实上这就是一些"池化资源"技术产生的原因。比方大家所熟悉的数据库连接池正是遵循这一思想而产生的,本文将介绍的线程池技术相同符合这一思想。

眼下,一些著名的大公司都特别看好这项技术,并早已经在他们的产品中应用该技术。比方IBM的WebSphere,IONA的Orbix 2000在SUN的 Jini中,Microsoft的MTS(Microsoft Transaction Server 2.0),COM+等。

4功能编辑

应用程序能够有多个线程。这些线程在休眠状态中须要耗费大量时间来等待事件发生。

其它线程可能进入睡眠状态,而且仅定期被唤醒以轮循更改或更新状态信息,然后再次进入休眠状态。为了简化对这些线程的管理,.NET框架为每一个进程提供了一个线程池,一个线程池有若干个等待操作状态。当一个等待操作完毕时,线程池中的辅助线程会运行回调函数。线程池中的线程由系统管理。程序猿不须要费力于线程管理,能够集中精力处理应用程序任务。

应用范围

fr=aladdin#" class="nslog:1019" title="编辑本段" style="text-decoration:none; color:rgb(136,136,136); height:15px; line-height:16px; padding-left:18px; background-color:transparent; font-size:12px; font-family:宋体; display:block">编辑

1、须要大量的线程来完毕任务。且完毕任务的时间比較短。

WEBserver完毕网页请求这种任务,使用线程池技术是很合适的。由于单个任务小,而任务数量巨大,你能够想象一个热门站点的点击次数。 但对于长时间的任务。比方一个Telnet连接请求,线程池的长处就不明显了。由于Telnet会话时间比线程的创建时间大多了。

2、对性能要求苛刻的应用,比方要求server迅速响应客户请求。
3、接受突发性的大量请求,但不至于使server因此产生大量线程的应用。突发性大量客户请求,在没有线程池情况下,将产生大量线程,尽管理论上大部分操作系统线程数目最大值不是问题,短时间内产生大量线程可能使内存到达极限,并出现"OutOfMemory"的错误。

Java线程池原理及实现

简介



    创建线程有两种方式:继承Thread或实现Runnable。

Thread实现了Runnable接口。提供了一个空的run()方法。所以不论是继承Thread还是实现Runnable,都要有自己的run()方法。

一个线程创建后就存在。调用start()方法就開始执行(执行run()方法)。调用wait进入等待或调用sleep进入休眠期,顺利执行完成或休眠被中断或执行过程中出现异常而退出。



wait和sleep比較:

      sleep方法有:sleep(long millis),sleep(long millis, long nanos),调用sleep方法后,当前线程进入休眠期,暂停运行,但该线程继续拥有监视资源的全部权。到达休眠时间后线程将继续运行,直到完毕。若在休眠期还有一线程中断该线程。则该线程退出。

      wait方法有:wait(),wait(long timeout),wait(long timeout, long nanos)。调用wait方法后,该线程放弃监视资源的全部权进入等待状态;

      wait():等待有其他的线程调用notify()或notifyAll()进入调度状态。与其他线程共同争夺监视。wait()相当于wait(0),wait(0, 0)。

      wait(long timeout):当其他线程调用notify()或notifyAll()。或时间到达timeout亳秒,或有其他某线程中断该线程。则该线程进入调度状态。

      wait(long timeout, long nanos):相当于wait(1000000*timeout + nanos)。仅仅只是时间单位为纳秒。

线程池:

    多线程技术主要解决处理器单元内多个线程运行的问题。它能够显著降低处理器单元的闲置时间。添加处理器单元的吞吐能力。

    

    如果一个server完毕一项任务所需时间为:T1 创建线程时间,T2 在线程中运行任务的时间,T3 销毁线程时间。

假设:T1 + T3 远大于 T2,则能够採用线程池。以提高server性能。

                一个线程池包含下面四个基本组成部分:

                1、线程池管理器(ThreadPool):用于创建并管理线程池。包含 创建线程池,销毁线程池,加入新任务;

                2、工作线程(PoolWorker):线程池中线程,在没有任务时处于等待状态。能够循环的运行任务;

                3、任务接口(Task):每一个任务必须实现的接口,以供工作线程调度任务的运行。它主要规定了任务的入口。任务运行完后的收尾工作,任务的运行状态等。

                4、任务队列(taskQueue):用于存放没有处理的任务。提供一种缓冲机制。

线程池技术正是关注怎样缩短或调整T1,T3时间的技术。从而提高server程序性能的。它把T1,T3分别安排在server程序的启动和结束的时间段或者一些空暇的时间段,这样在server程序处理客户请求时,不会有T1,T3的开销了。



    线程池不仅调整T1,T3产生的时间段。并且它还显著降低了创建线程的数目,看一个样例:



    如果一个server一天要处理50000个请求,而且每一个请求须要一个单独的线程完毕。在线程池中,线程数通常是固定的,所以产生线程总数不会超过线程池中线程的数目,而如果server不利用线程池来处理这些请求则线程总数为50000。一般线程池大小是远小于50000。所以利用线程池的server程序不会为了创建50000而在处理请求时浪费时间,从而提高效率。





/** 线程池类。工作线程作为其内部类 **/



import java.util.Collections;

import java.util.Date;

import java.util.LinkedList;

import java.util.List;



import org.apache.log4j.Logger;



/**

* 线程池

* 创建线程池,销毁线程池,加入新任务



* @author obullxl

*/

public final class ThreadPool {

    private static Logger logger = Logger.getLogger(ThreadPool.class);

    private static Logger taskLogger = Logger.getLogger("TaskLogger");



    private static boolean debug = taskLogger.isDebugEnabled();

    // private static boolean debug = taskLogger.isInfoEnabled();

    /* 单例 */

    private static ThreadPool instance = ThreadPool.getInstance();



    public static final int SYSTEM_BUSY_TASK_COUNT = 150;

    /* 默认池中线程数 */

    public static int worker_num = 5;

    /* 已经处理的任务数 */

    private static int taskCounter = 0;



    public static boolean systemIsBusy = false;



    private static List<Task> taskQueue = Collections

            .synchronizedList(new LinkedList<Task>());

    /* 池中的全部线程 */

    public PoolWorker[] workers;



    private ThreadPool() {

        workers = new PoolWorker[5];

        for (int i = 0; i < workers.length; i++) {

            workers[i] = new PoolWorker(i);

        }

    }



    private ThreadPool(int pool_worker_num) {

        worker_num = pool_worker_num;

        workers = new PoolWorker[worker_num];

        for (int i = 0; i < workers.length; i++) {

            workers[i] = new PoolWorker(i);

        }

    }



    public staticsynchronizedThreadPool
getInstance() {

        if (instance == null)

            return new ThreadPool();

        return instance;

    }

    /**

    * 添加新的任务

    * 每添加一个新任务。都要唤醒任务队列

    * @param newTask

    */

    public void addTask(Task newTask) {

        synchronized (taskQueue) {

            newTask.setTaskId(++taskCounter);

            newTask.setSubmitTime(new Date());

            taskQueue.add(newTask);

            /* 唤醒队列, 開始运行 */

            taskQueue.notifyAll();

        }

        logger.info("Submit Task<" + newTask.getTaskId() + ">: "

                + newTask.info());

    }

    /**

    * 批量添加新任务

    * @param taskes

    */

    public void batchAddTask(Task[] taskes) {

        if (taskes == null || taskes.length == 0) {

            return;

        }

        synchronized (taskQueue) {

            for (int i = 0; i < taskes.length; i++) {

                if (taskes[i] == null) {

                    continue;

                }

                taskes[i].setTaskId(++taskCounter);

                taskes[i].setSubmitTime(new Date());

                taskQueue.add(taskes[i]);

            }

            /* 唤醒队列, 開始运行 */

            taskQueue.notifyAll();

        }

        for (int i = 0; i < taskes.length; i++) {

            if (taskes[i] == null) {

                continue;

            }

            logger.info("Submit Task<" + taskes[i].getTaskId() + ">: "

                    + taskes[i].info());

        }

    }

    /**

    * 线程池信息

    * @return

    */

    public String getInfo() {

        StringBuffer sb = new StringBuffer();

        sb.append("\nTask Queue Size:" + taskQueue.size());

        for (int i = 0; i < workers.length; i++) {

            sb.append("\nWorker " + i + " is "

                    + ((workers[i].isWaiting()) ? "Waiting." : "Running."));

        }

        return sb.toString();

    }

    /**

    * 销毁线程池

    */

    public synchronized void destroy() {

        for (int i = 0; i < worker_num; i++) {

            workers[i].stopWorker();

            workers[i] = null;

        }

        taskQueue.clear();

    }



    /**

    * 池中工作线程

    * 

    * @author obullxl

    */

    private class PoolWorker extends Thread {

        private int index = -1;

        /* 该工作线程是否有效 */

        private boolean isRunning = true;

        /* 该工作线程能否够运行新任务 */

        private boolean isWaiting = true;



        public PoolWorker(int index) {

            this.index = index;

            start();

        }



        public void stopWorker() {

            this.isRunning = false;

        }



        public boolean isWaiting() {

            return this.isWaiting;

        }

        /**

        * 循环运行任务

        * 这或许是线程池的关键所在

        */

        public void run() {

            while (isRunning) {

                Task r = null;

                synchronized (taskQueue) {

                    while (taskQueue.isEmpty()) {

                        try {

                            /* 任务队列为空,则等待有新任务增加从而被唤醒 */

                            taskQueue.wait(20);

                        } catch (InterruptedException ie) {

                            logger.error(ie);

                        }

                    }

                    /* 取出任务运行 */

                    r = (Task) taskQueue.remove(0);

                }

                if (r != null) {

                    isWaiting = false;

                    try {

                        if (debug) {

                            r.setBeginExceuteTime(new Date());

                            taskLogger.debug("Worker<" + index

                                    + "> start execute Task<" + r.getTaskId() + ">");

                            if (r.getBeginExceuteTime().getTime()

                                    - r.getSubmitTime().getTime() > 1000)

                                taskLogger.debug("longer waiting time. "

                                        + r.info() + ",<" + index + ">,time:"

                                        + (r.getFinishTime().getTime() - r

                                                .getBeginExceuteTime().getTime()));

                        }

                        /* 该任务是否须要马上运行 */

                        if (r.needExecuteImmediate()) {

                            new Thread(r).start();

                        } else {

                            r.run();

                        }

                        if (debug) {

                            r.setFinishTime(new Date());

                            taskLogger.debug("Worker<" + index

                                    + "> finish task<" + r.getTaskId() + ">");

                            if (r.getFinishTime().getTime()

                                    - r.getBeginExceuteTime().getTime() > 1000)

                                taskLogger.debug("longer execution time. "

                                        + r.info() + ",<" + index + ">,time:"

                                        + (r.getFinishTime().getTime() - r

                                                .getBeginExceuteTime().getTime()));

                        }

                    } catch (Exception e) {

                        e.printStackTrace();

                        logger.error(e);

                    }

                    isWaiting = true;

                    r = null;

                }

            }

        }

    }

}



/** 任务接口类 **/



package org.ymcn.util;



import java.util.Date;



/**

* 全部任务接口

* 其它任务必须继承訪类



* @author obullxl

*/

public abstract class Task implements Runnable {

    // private static Logger logger = Logger.getLogger(Task.class);

    /* 产生时间 */

    private Date generateTime = null;

    /* 提交运行时间 */

    private Date submitTime = null;

    /* 開始运行时间 */

    private Date beginExceuteTime = null;

    /* 运行完毕时间 */

    private Date finishTime = null;



    private long taskId;



    public Task() {

        this.generateTime = new Date();

    }



    /**

    * 任务运行入口

    */

    public void run() {

        /**

        * 相关运行代码

        * 

        * beginTransaction();

        * 

        * 运行过程中可能产生新的任务 subtask = taskCore();

        * 

        * commitTransaction();

        * 

        * 添加新产生的任务 ThreadPool.getInstance().batchAddTask(taskCore());

        */

    }



    /**

    * 全部任务的核心 所以特别的业务逻辑运行之处

    * 

    * @throws Exception

    */

    public abstract Task[] taskCore() throws Exception;



    /**

    * 是否用到数据库

    * 

    * @return

    */

    protected abstract boolean useDb();



    /**

    * 是否须要马上运行

    * 

    * @return

    */

    protected abstract boolean needExecuteImmediate();



    /**

    * 任务信息

    * 

    * @return String

    */

    public abstract String info();



    public Date getGenerateTime() {

        return generateTime;

    }



    public Date getBeginExceuteTime() {

        return beginExceuteTime;

    }



    public void setBeginExceuteTime(Date beginExceuteTime) {

        this.beginExceuteTime = beginExceuteTime;

    }



    public Date getFinishTime() {

        return finishTime;

    }



    public void setFinishTime(Date finishTime) {

        this.finishTime = finishTime;

    }



    public Date getSubmitTime() {

        return submitTime;

    }



    public void setSubmitTime(Date submitTime) {

        this.submitTime = submitTime;

    }



    public long getTaskId() {

        return taskId;

    }



    public void setTaskId(long taskId) {

        this.taskId = taskId;

    }



}







转自:http://hi.baidu.com/obullxl/blog/item/ee50ad1ba8e8ff1f8718bf66.html

版权声明:本文博客原创文章。博客,未经同意,不得转载。

最新文章

  1. Python for Informatics 第11章 正则表达式五(译)
  2. 转!! PreparedStatement是如何防止SQL注入的
  3. js 横幅播放
  4. SQL Server 2005中更改sa的用户名和密码
  5. Spring 框架 详解 (四)------IOC装配Bean(注解方式)
  6. pager分页框架体会
  7. JAVA基础总结一:
  8. (转)c# math 计算两点之间的角度公式
  9. linux下不重启添加硬盘
  10. 通用PE u盘启动盘制作
  11. ok6410 u-boot-2012.04.01移植六完善MLC NAND支持
  12. C#中StreamReader读取中文时出现乱码问题总结
  13. 什么是C语言。C语言入门
  14. js判断参数是否为非数字
  15. Servlet_note
  16. JQuery模拟常见的拖拽验证
  17. 吴恩达机器学习笔记14-逻辑回归(Logistic Regression)
  18. node的经典事件监听
  19. Linux里的稀疏文件
  20. javaScript书写规范

热门文章

  1. spark安装与调试
  2. POJ 1775 Sum of Factorials (ZOJ 2358)
  3. Opencv在视频中静态、动态方式绘制矩形框ROI
  4. [转载]Ocelot简易教程(二)之快速开始1
  5. ECharts.js 超简单入门(本质canvas)
  6. 关于ulimit -a中需要修改的两个值
  7. 【codeforces 754A】Lesha and array splitting
  8. 数字图像处理原理与实践(MATLAB版)勘误表
  9. html5和html的区别是什么(精问)
  10. 【物理】概念的理解 —— Phase(相位)