彩虹天堂
技术源于生活
posts - 0,  comments - 2,  trackbacks - 0
线程使得计算机可以同时执行多个任务,并且各个任务之间相互分离,各自的独立运行,当然资源还是由机算机来分配的,像内存,文件句柄,安全证书,如果需要的话,线程会通过一些原如的机制相互进行通信:Socket,信号处理(signal handlers),共享内存,信号量和文件等等。

而随着计算机朝着多核的方向迈进,计算机的处理方式也由原来的单线程安照时间片的处理方式改变为多核同时处理时间片(参考:JAVA CONCURRENCY IN PRACTICE),所以更好的理解多线程有助于我们写出效率更高的程序。

今天我想讨论的是如何更好的利用JAVA的多线程来执行任务。现在大多数服务器像大家常听说的:Web服务器,邮件服务器,文件服务器,EJB容器等,都是接受远程客户通过网络连接发送的请求,然后对其做出处理,而且每个请求之间不会受其他请求的影响,并且,服务器只须用其很小的一部分资源就可以处理单一的消息。

而服务器内部的调动策略是我们今天要讨论的。
第一种,代码如下:
Class SingleThreadWebServer{
    Public static void main(String [] args) throws IOException{
        ServerSocket socket=new ServerSocket(80);
        While(true){
            Socket connection=socket.accept();
            //处理connection
        }
    }
}
这种策略一次只能处理一个请求,效率无疑是非常差的。当系统需要在处理完connection,以后才会回到头来调用accept().我来简单的解释一下为什么
1.    当socket接受到一个请求A时,如果这时再过来一个B请求,而系统正在处理当前的请求,固无法去处理B请求,此时B请求会暂时的阻塞,而B请求的阻塞而使服务器浪费的资源是不比处理A资源时小的。等到A请求处理完时。才能继续处理
2.    在等待请求时,也就是单线程服务在等待它的I/O操作,CPU会处于闲置状态,当然利用率也非常之低了。
所以,这种使用策略不是很推荐使用,除非你的服务器只有唯一的一个用户,而且服务器在同一时间内只需只时处理一个请求除外。

第二种,代码如下:
Class ThreadPerTaskWebServer{
    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 runj(){
                    //处理connection
}
            };
            new Thread(task).start();
        }
    }
}
在第二种情况下,系统的主线也就是main的主方法不断的交替运行“接受外部连接”,“转发请求”,而且主循环为每个连接都创建一个新线程以处理请求,且并不在主循环内部处理它。和第一种方法相比,他有下面几种优势
1.    执行任务不放在主线程,主线程主要负责等待新的连接,这样程序就可以在完成前面的请求之前在接受新的请求,响应也相应的提高了
2.    程序并行的处理任务,因为多个线程可以在完成请求之前接新请求,程序的吞吐量得到了很大的提高
3.    代码是线程安全的,多个任务并发的调用它。
第二种是对第一种的良好的改进,也是现在大多数主流的Web服务器所用的连接和使用方式,而且只要请求的到达速度没有超出服务器的请求能力,这种方法也可以说是比较好的解决多请求的方案

当然,不能不看到。第二种方法也有其缺点:
1.    因为每个任务都会为其创建线程,所以,当线程使用过多时,系统和虚拟机会因为创建线程而消耗大量的资源
2.    而且要考虑到,如果创建线程过来,内存有限时,而且可运行的线程多于可用的处理器数,线程将会空闲,大量空闲没处理的线程就会占据很大的闪存,所以,当你的线程的数量已经达到CPU能够处理的最大数时。再创建只会影响效率
3.    Thread在创建线程时,会要求内存空间给出一定的堆占空间,当使用过多时。就会导致虚拟机的OutOfMemoryError。本人因为工作原因也是经常用多线程,如果暴这个异常。就不得不重启服务器。
所以,我们可以总结出,在一定的范围内,增加线程可以提高系统的吞吐量,一旦超出范围,线程创建再多只会OutOfMemoryError。所以我们应该想办法设定一个范围来限制应用程序可以创建的线程数,然后测试其最大所能承受的范围,从而构造良好的健康的程序。具体的明天我们继续讨论,如何利用线程池来写出更好的多线程程序。
--------------------------------
Q9原创。
posted on 2008-05-02 23:43 bcterry 阅读(135) 评论(0)  编辑  收藏

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


网站导航:
 

<2024年11月>
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567

留言簿

文章档案

搜索

  •  

最新评论