昨天我们在BLOG中讨论了最常用到的创建线程方法,介绍了他们的用法,优点以及他们的不足之处。当然,我们介绍的两种方法都不是创建线程的最完美方法,方法一无法并发的处理多个任务,而方法二的话在CPU处理的界限内可以很好的完成任务,但是一旦超出CPU所能承受的压力,就会导致程序莫名的死掉,所以我们的目标是创建安全的,可使用的,以及高效的线程。
线程池:线程池是指管理线程的同构池,他可以持有所有等待执行的任务,从队例中获取下一个任务,执行,然后回来继续等待另一个线程。和第二种方法比线程池有什么优势呢?
1. 他重用存在的线程,而不是创建新的线程,这样做的好处是,在请求到达时,工作线程存在,用于创建线程的等待时间并不会延迟任务的执行,响应性提高了。
2. 通过调整线程池的大小,可以防止过多的线程被创建,不会过多的浪费资源。
所以,使用线程池是使用线程的最明智选择,只有当CPU和内存资源使用处理一个稳定阶段时,我们也才有机会去做调优,管理,监视,记录日志等其他事情。
今天我们介绍第三种方法:利用线程池(Thread pool),当然我们这里说的线程池并不需要我们自已去实现或者找第三方的实现。在我们使用JDK1.5开发时,Sun已经帮我们写好,我们需要学的就是如何去合理的使用以及调用他们了。也就是java.util.concurrent下面的接口Executor.
我们先看看API中关于Executor的使用说明:
执行已提交的 Runnable 任务的对象。此接口提供一种将任务提交与每个任务将如何运行的机制(包括线程使用的细节、调度等)分离开来的方法。通常使用 Executor 而不是显式地创建线程
具体如何使用Executor接口呢?下面我们看一个简单的DEMO:
public class TestExecute {
//设定线程池的大小。大小不空
private static final int NTHREADS=100;
//定义线程池
private static final Executor exec=Executors.newFixedThreadPool(NTHREADS);
public static void main(String[] args)throws IOException{
ServerSocket socket=new ServerSocket(80);
while(true){
final Socket connection=socket.accept();
Runnable task=new Runnable(){
public void run(){
//handlerequest(conntection)
}
};
exec.execute(task);
}
}
}
从上面的代码我们可以看到,在main方法里面其他没有什么不同,就是最后一步,exec.execute(task),将这个要执行的线程放入自已的线程池中,当然然后执行的方法就是用的JAVA线程池作者的策略来执行了。我们不知道他何时执行开始,何时执行结束,但是有一点可以确定,线程池可以更好的优化程序的速度以及效率。
不过,使用Executor的类必须实现Runnable接口,然尔大家都知道如果是使实Runnable的类执行run() 方法,不能返回值当然也无法抛出已检查异常。当然,用Executor可以有办法得到返回值和抛出已检查异常。
-----------------------------------
Q9原创。
posted on 2008-05-03 00:01
bcterry 阅读(143)
评论(0) 编辑 收藏