最近在学习线程池、内存控制等关于提高程序运行性能方面的编程技术,在网上看到有一哥们写得不错,故和大家一起分享。

[回复享]Java线程池的原理与实现


这几天主要是狂看源程序,在弥补了一些以前知识空白的同时,也学会了不少新的知识(意大利国家石油公司)或者称为新技术吧。
线程池就是其中之一,一提到线程,我们会想到以前操作系统》的生产者与消费者,信号量,同步控制等等。
一提到池,我们会想到数据库连接池,但是线程池又如何呢?


建议以下为:在阅读本文前,先理一理同步的知识,特别是同步的同步关键字的用法。
关于我对同步的认识,要缘于大三年的一本书,书名好像是 Java语言实战,这本书写得实在太妙了,真正的从理论到实践,从截图分析到.字节码分析。哇,我想市场上很难买到这么精致的书了。作为一个Java语言爱好者,我觉得绝对值得一读。
我对此书印象最深之一的就是:等于()方法,由浅入深,经典!
还有就是同步了,其中提到了我的几个编程误区,以前如何使用同步提高性能等等,通过学习,使我对同步的认识进一步加深。


简单介绍

    创建线程有两种方式:继承线程可运行线程可运行接口,提供了一个空的运行()方法,所以不论是继承线程可运行,运行()
    一个线程创建后就存在,调用启动()缔约方(运行),等待进入等待或调用睡觉进入休眠期,顺利运行完毕或休眠被中断或运行过程中出现异常而退出。

等待和睡眠
睡眠:睡眠(长毫)、睡眠(长毫微秒、长纳米)、睡眠路线规划,路线规划,路线规划
wait(),wait(长超时),waite(长超时,长纳米)方法后,该线程放弃监视资源的所有权进入等待状态;
等待():等待有其它的线程调用notify()或notifyAll()进入调度状态,与其它线程共同争夺监视。wait()等待(0),等待(0,0)
等待(长超时):当其它线程调用notify()notifyAll(),超时亳秒,或有其它某线程中断该线程,则该线程进入调度状态。
wait(long timeout,long nanos):等待(1000000*timeout+nanos只不过时间单位为纳秒。



线程池:
    多线程技术主要解决处理器单元内多个线程执行的问题,它可以显著减少处理器单元的闲置时间,增加处理器单元的吞吐能力。
   
    假设一个服务器完成一项任务所需时间为:T1类创建线程时间,T2段在线程中执行任务的时间,T3销毁线程时间。
   
时间:T1+T3 T2则可以采用线程池,以提高服务器性能。
                一个线程池包括以下四个基本组成部分:
1、线程池(ThreadPool):用于创建并管理线程池,包括 创建线程池,销毁线程池,添加新任务;
2、工程作业(池工):路线图
3、任务:每个任务必须实现的接口,以供工作线程调度任务的执行,它主要规定了任务的入口,任务执行完后的收尾工作,任务的执行状态等;
4、任务队列(taskQueue):用于存放没有处理的任务。提供一种缓冲机制。
               
    线程池技术正是关注如何缩短或调整T1、T3时间的技术,从而提高服务器程序性能的。它把T1、T3分别安排在服务器程序的启动和结束的时间段或者一些空闲的时间段,这样在服务器程序处理客户请求时,不会有T1、T3

    线程池不仅调整T1、T3产生的时间段,而且它还显著减少了创建线程的数目,看一个例子:

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


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

包org.ymcn.util;

导入java.util。收藏;
导入java.util。日期;
导入java.util。LinkedList;
导入java.util。列表;

导入org.apache.log4j。记录器;

/**
*线程池
* 创建线程池,销毁线程池,添加新任务
*
*@作者obullxl
*/
公共最终类ThreadPool{
private static Logger Logger=Logger.getLogger(ThreadPool.class);
private static Logger taskLogger=Logger.getLogger(“taskLogger”);

私有静态布尔调试=taskLogger.isDebugEnabled();
//私有静态布尔调试=taskLogger.isInfoEnabled();
    /* 单例 */
私有静态线程池实例=线程池.getInstance();

公共静态最终int SYSTEM_BUSY_TASK_COUNT=150;
/*默认池中线程数 */
public static int worker_num=5;
    /* 已经处理的任务数 */
private static int taskCounter=0;

公共静态布尔系统IsBusy=false;

私有静态列表<Task>taskQueue=集合
.synchronizedList(新的LinkedList<Task>());
    /* 池中的所有线程 */
公共池工人[]工人;

专用线程池(){
workers=新PoolWorker[5];
for(int i=0;i<workers.length;i++){
workers[i]=新的PoolWorker(i);
        }
    }

专用线程池(int pool_worker_num){
worker_num=池worker_num;
workers=新PoolWorker[worker_num];
for(int i=0;i<workers.length;i++){
workers[i]=新的PoolWorker(i);
        }
    }

公共静态同步线程池getInstance(){
if(实例==空)
return new ThreadPool();
返回实例;
    }
    /**
    * 增加新的任务
*每增加一个新任务,都要唤醒任务队列
*@param newTask
    */
public void addTask(任务newTask){
同步(taskQueue){
newTask.setTaskId(++任务计数器);
newTask.setSubmitTime(new Date());
taskQueue.add(newTask);
/*唤醒队列, 开始执行 */
taskQueue.notifyAll();
        }
logger.info(“提交任务<”+newTask.getTaskId()+“>:”
+newTask.info());
    }
/**
    * 批量增加新任务
*@param任务
    */
public void batchAddTask(Task[]taskes){
if(taskes==null | | taskes.length==0){
回报;
        }
同步(taskQueue){
for(int i=0;i<taskes.length;i++){
if(任务[i]==空){
继续;
                }
tasks[i].setTaskId(++任务计数器);
taskes[i].setSubmitTime(new Date());
taskQueue.add(任务[i]);
            }
            /* 唤醒队列, 开始执行 */
taskQueue.notifyAll();
        }
for(int i=0;i<taskes.length;i++){
if(taskes[i]==空){
继续;
            }
logger.info(“提交任务<”+taskes[i].getTaskId()+“>:”
+任务[i].info());
        }
    }
    /**
    * 线程池信息
*@返回
*/
公共字符串getInfo(){
StringBuffer sb=新的StringBuff();
sb.append(“任务队列大小:”+taskQueue.Size());
for(int i=0;i<workers.length;i++){
sb.append(“\nWorker”+i+“是”
+((workers[i].isWaiting())?“等待。”:“正在运行。”);
        }
将某人返回字符串();
    }
    /**
    * 销毁线程池
    */
公共同步void destroy(){
for(int i=0;i<worker_num;i++){
workers[i].stopWorker();
工人[i]=null;
        }
taskQueue.clear();
    }

    /**
    * 池中工作线程
    *
*@author obullxl
    */
私有类PoolWorker扩展了Thread{
私有int索引=-1;
        /* 该工作线程是否有效 */
私有布尔值isRunning=true;
/*该工作线程是否可以执行新任务 */
private boolean isWaiting=true;

公共PoolWorker(int index){
this.index=索引;
启动();
        }

公共void stopWorker(){
this.isRunning=false;
}

公共布尔值isWaiting(){
return this.isWaiting;
        }
        /**
        * 循环执行任务
*这也许是线程池的关键所在
        */
公共void run(){
while(正在运行){
任务r=空;
同步(taskQueue){
while(taskQueue.isEmpty()){
尝试{
                            /* 任务队列为空,则等待有新任务加入从而被唤醒 */
taskQueue.wait(20);
}捕获(InterruptedException ie){
记录器错误(ie);
                        }
                    }
                    /* 取出任务执行 */
r=(Task)taskQueue.remove(0);
                }
如果(r!=空){
isWaiting=false;
尝试{
if(调试){
r.setBeginExceuteTime(新日期());
taskLogger.debug(“Worker<”+索引
+“>开始执行任务<”+r.getTaskId()+“>”);
if(r.getBeginExceuteTime().getTime()
-r.getSubmitTime().getTime()>1000)
taskLogger.debug(“等待时间更长。”
+r.info()+“,<”+index+“>,时间:”
+(r.getFinishTime().getTime()-r
.getBeginExcuteTime().getTime());
                        }
                        /* 该任务是否需要立即执行 */
如果(r.needExecuteImmediate()){
新线程(r).start();
}其他{
r.run();
                        }
if(调试){
r.setFinishTime(新日期());
taskLogger.debug(“Worker<”+索引
+“>完成任务<”+r.getTaskId()+“>”);
if(r.getFinishTime().getTime()
-r.getBeginExceuteTime().getTime()>1000)
taskLogger.debug(“执行时间更长。”
+r.info()+“,<”+index+“>,时间:”
+(r.getFinishTime().getTime()-r
.getBeginExceuteTime().getTime()));
                        }
}捕获(异常e){
e.printStackTrace();
记录器错误(e);
                    }
isWaiting=true;
r=空;
                }
            }
        }
    }
}

/****/

包org.ymcn.util;

导入java.util。日期;

/**
*所有任务接口
* 其他任务必须继承访类
*
*@author obullxl
*/
公共抽象类Task实现Runnable{
//私有静态Logger Logger=Logger.getLogger(Task.class);
    /* 产生时间 */
private Date generateTime=空;
/*提交执行时间 */
private Date submitTime=null;
    /* 开始执行时间 */
private Date beginExceuteTime=null;
/*执行完成时间 */
private Date finishTime=null;

private long taskId;

公共任务(){
this.generateTime=新日期();
    }

    /**
    * 任务执行入口
    */
公共void run(){
        /**
        * 相关执行代码
        *
*beginTransaction();
        *
        * 执行过程中可能产生新的任务 子任务=taskCore();
        *
*commitTransaction();
        *
        * 增加新产生的任务 ThreadPool.getInstance().batchAddTask(taskCore());
        */
    }

    /**
    * 所有任务的核心 所以特别的业务逻辑执行之处
    *
*@throws异常
    */
公共抽象任务[]taskCore()引发异常;

/**
    * 是否用到数据库
    *
*@返回
    */
受保护的抽象布尔值useDb();

    /**
    * 是否需要立即执行
    *
*@返回
    */
受保护的抽象布尔型needExecuteImmediate();

    /**
    * 任务信息
    *
*@return字符串
    */
public abstract String info();

公共日期getGenerateTime(){
返回生成时间;
    }

公共日期getBeginExceuteTime(){
返回开始ExceuteTime;
    }

public void setBeginExcuteTime(日期开始ExcuteTime){
this.beginExceuteTime=开始ExceuteTime;
    }

公共日期getFinishTime(){
返回finishTime;
    }

public void setFinishTime(日期完成时间){
this.finishTime=完成时间;
    }

公共日期getSubmitTime(){
返回提交时间;
    }

public void setSubmitTime(日期提交时间){
this.submitTime=提交时间;
    }

public long getTaskId(){
return taskId;
    }

public void setTaskId(长任务Id){
this.taskId=任务Id;
    }

}



转自:http://hi.baidu.com/obullxl/blog/item/ee50ad1ba8e8ff1f8718bf66.html
发布时间:2008-10-17 23:20李威威阅读(105965)评论(12) 编辑 收藏
评论
  • # 回复:Java线程池的原理与实现
    强尼戴普
    发布时间:2012-06-18 17:03
    代码可以加于适当注释么?  回复  更多   
  • # 回复:Java线程池的原理与实现
    克每小时
    发布时间:2012-06-29 19:43
    你说的是哪本书??  回复  更多评论   
  • # 回复:Java线程池的原理与实现[未登录]
    阿兹强
    发布时间:2012-09-05 18:13
    学习下,就是注释好少。  回复  更多评论   
  • # 回复:Java线程池的原理与实现
    印度卢比
    发布时间:2013-03-11 19:38
    写的不错,我也一直纳闷,线程池是怎么保持线程的,现在重要明白了。
      回复  更多评论   
  • # 回复:Java线程池的原理与实现
    张永红
    发布时间:2013-08-27 11:10
    例子中有一点不太明白,有个参数叫做 是否立即执行?
    为什么为真时,是创建另外的线程执行。
    为假时,是直接调用奔跑
    这个我感觉跟立即执行没什么关系,反而参数的意思是,是否需要额外的线程执行。  回复  更多评论   
  • # 回复:Java线程池的原理与实现
    阿尔维斯
    发布时间:2013-08-30 11:51
    立即执行应该是在提交任务的时候,首先是查看线程池中是否有空闲的工作线程,如果有就执行,如果没有就开启另外的线程执行。我的理解是这样。  回复  更多评论   
  • # 关于:Java线程池的原理与实现
    测试者
    发布时间:2014-02-18 14:25
    你好,你说的那本书能想起全名吗  回复  更多评论   
  • # 关于:Java线程池的原理与实现
    可以
    发布时间:2014-03-31 11:38
    @测试者
    应该是Java语言开发实战经典,李兴华著  回复  更多评论   
  • # 回复:Java线程池的原理与实现
    迪达福尔
    发布时间:2014-11-18 12:52
    可以去支柱教程网上看看,有一篇文章是讲解构建一个简单的线程池的感觉不错。  回复  更多评论   
  • # 回复:Java线程池的原理与实现
    迪达福尔
    发布时间:2014-11-18 12:53
    可以看看这篇文章,构建一个简单的线程池:http://www.strutshome.com/index.php/archives/710  回复  更多评论   
  • # 回复:Java线程池的原理与实现
    xxxxx个
    发布时间:2015-09-08 22:09
    祸害不少人  回复  更多评论   
  • # 回复:Java线程池的原理与实现
    回复:Java线程池的原理与实现
    发布时间:2015-12-07 10:13
    关于:Java线程池的原理与实现  回复  更多评论   

只有注册用户登录后才能发表评论。


网站导航: