闂傚倸鍊搁崐鎼佸磹閹间礁纾圭€瑰嫭鍣磋ぐ鎺戠倞妞ゆ巻鍋撴潻婵嬫⒑闁偛鑻晶鎾煛鐏炲墽銆掗柍褜鍓ㄧ紞鍡涘磻閸涱厾鏆︾€光偓閸曨剛鍘搁悗鍏夊亾闁逞屽墴瀹曚即寮介婧惧亾娴g硶妲堟俊顖氬槻閻楁岸姊洪崨濠傚闁稿鎸歌濠㈣泛顑勭换鍡涙煟閹板吀绨婚柍褜鍓氶崹鍨暦閺囩喓绡€婵﹩鍓涢鍡涙⒑鐠恒劌娅愰柟鍑ゆ嫹 (0) +1 闂傚倸鍊搁崐鎼佸磹瀹勬噴褰掑炊瑜忛弳锕傛煕椤垵浜濋柛娆忕箳閳ь剙绠嶉崕閬嶅箯鐎n喖瑙﹂悗锝庡枟閻撴洟鏌嶉埡浣告灓婵炲牄鍨归湁缁绢參鏀辩€氾拷 (0) +1 闂傚倸鍊搁崐鎼佸磹閹间礁纾归柟闂寸绾惧綊鏌熼梻鎾闁稿鍨块幃妤€鈽夊▎瀣窗濡炪倐鏅滈悡锟犲蓟閿濆绠i柨婵嗘-濡嫮绱撴担鍝勵€岄柛銊ョ埣瀵濡搁埡鍌氫簽闂佺ǹ鏈粙鎴︻敂閿燂拷 (0) +1
闂傚倸鍊搁崐鎼佸磹閹间礁纾圭€瑰嫭鍣磋ぐ鎺戠倞妞ゆ巻鍋撴潻婵嬫⒑闁偛鑻晶鎾煛鐏炲墽銆掗柍褜鍓ㄧ紞鍡涘磻閸涱厾鏆︾€光偓閸曨剛鍘搁悗鍏夊亾闁逞屽墴瀹曚即寮介婧惧亾娴g硶妲堟俊顖氬槻閻楁岸姊洪崨濠傚闁稿鎸歌濠㈣泛顑勭换鍡涙煟閹板吀绨婚柍褜鍓氶崹鍨暦閺囥垹钃熼柕澶堝劚閻庮參姊虹粔鍡楀濞堟棃鏌﹂崘顏勬灈闁哄矉缍佸顕€宕堕妷銏犱壕闁逞屽墴閺屾稓鈧綆鍋呯亸顓㈡煃閽樺妲搁柍璇茬Ч椤㈡ǹ顦辩紒銊ャ偢閺岀喐绗熼崹顔碱潎閻庤娲橀崕濂杆囬鈧弻锟犲焵椤掑嫭鍤嶉柕澶涚导缁ㄥ姊洪崫鍕窛闁稿鍋よ棢闁绘劗鍎ら崐鍨叏濡厧浜鹃悗姘炬嫹闂傚倸鍊搁崐鎼佸磹閹间礁纾瑰瀣捣閻棗銆掑锝呬壕濡ょ姷鍋為悧鐘汇€侀弴銏犖ч柛鈩冦仦缁剝淇婇悙顏勨偓鏍礉瑜忕划濠氬箣閻樺樊妫滈梺绉嗗嫷娈曢柣鎾存礋閺岀喖鏌囬敃鈧悘閬嶆煕閵堝拋鍎旈柡灞诲€濆鍫曞箰鎼粹€叉樊闂備礁鎼張顒傜矙閹达箑鐓″璺号堥弸搴ㄦ煙闁箑鏋ら柍璇茬箳缁辨捇宕掑顑藉亾妞嬪孩濯奸柡灞诲劚閻ら箖鏌eΟ娆惧殭闁藉啰鍠栭弻锝夊籍閸屾瀚涢梺杞扮缁夌數鎹㈠┑鍥╃瘈闁稿本纰嶉悘鎾绘⒑閸濆嫭锛嶉柛妯恒偢閳ユ棃宕橀鍢壯囨煕閹扳晛濡煎┑顔惧厴濮婃椽鎮烽弶鎸庮唨闂佺懓鍤栭幏锟�>>

正在阅读:Java I/O API之性能分析 (上)Java I/O API之性能分析 (上)

2004-12-13 10:07 出处:CSDN 作者:legendinfo 责任编辑:huangpeidan

  摘要:

  IO API的可伸缩性对Web应用有着极其重要的意义。Java 1.4版以前的API中,阻塞I/O令许多人失望。从J2SE 1.4版本开始,Java终于有了可伸缩的I/O API。本文分析并计算了新旧I/O API在可伸缩性方面的差异。

  一、概述

  IO API的可伸缩性对Web应用有着极其重要的意义。Java 1.4版以前的API中,阻塞I/O令许多人失望。从J2SE 1.4版本开始,Java终于有了可伸缩的I/O API。本文分析并计算了新旧IO API在可伸缩性方面的差异。Java向Socket写入数据时必须调用关联的OutputStream的write()方法。只有当所有的数据全部写入时,write()方法调用才会返回。倘若发送缓冲区已满且连接速度很低,这个调用可能需要一段时间才能完成。如果程序只使用单一的线程,其他连接就必须等待,即使那些连接已经做好了调用write()的准备也一样。为了解决这个问题,你必须把每一个Socket和一个线程关联起来;采用这种方法之后,当一个线程由于I/O相关的任务被阻塞时,另一个线程仍旧能够运行。

  尽管线程的开销不如进程那么大,但是,考虑到底层的操作平台,线程和进程都属于消耗大量资源的程序结构。每一个线程都要占用一定数量的内存,而且除此之外,多个线程还意味着线程上下文的切换,而这种切换也需要昂贵的资源开销。因此,Java需要一个新的API来分离Socket与线程之间过于紧密的联系。在新的Java I/O API(java.nio.*)中,这个目标终于实现了。

  本文分析和比较了用新、旧两种I/O API编写的简单Web服务器。由于作为Web协议的HTTP不再象原来那样只用于一些简单的目的,因此这里介绍的例子只包含关键的功能,或者说,它们既不考虑安全因素,也不严格遵从协议规范。

  二、用旧API编写的HTTP服务器

  首先我们来看看用旧式API编写的HTTP服务器。这个实现只使用了一个类。main()方法首先创建了一个绑定到8080端口的ServerSocket:


  public static void main() throws IOException {
  ServerSocket serverSocket = new ServerSocket(8080);
  for (int i=0; i < Integer.parseInt(args[0]); i++) {
  new Httpd(serverSocket);
  }
  }

  接下来,main()方法创建了一系列的Httpd对象,并用共享的ServerSocket初始化它们。在Httpd的构造函数中,我们保证每一个实例都有一个有意义的名字,设置默认协议,然后通过调用其超类Thread的start()方法启动服务器。此举导致对run()方法的一次异步调用,而run()方法包含一个无限循环。

  在run()方法的无限循环中,ServerSocket的阻塞性accpet()方法被调用。当客户程序连接服务器的8080端口,accept()方法将返回一个Socket对象。每一个Socket关联着一个InputStream和一个OutputStream,两者都要在后继的handleRequest()方法调用中用到。这个方法将读取客户程序的请求,经过检查和处理,然后把合适的应答发送给客户程序。如果客户程序的请求合法,通过sendFile()方法返回客户程序请求的文件;否则,客户程序将收到相应的错误信息(调用sendError())方法。


  while (true) {
  ...
  socket = serverSocket.accept();
  ...
  handleRequest();
  ...
  socket.close();
  }

  现在我们来分析一下这个实现。它能够出色地完成任务吗?答案基本上是肯定的。当然,请求分析过程还可以进一步优化,因为在性能方面StringTokenizer的声誉一直不佳。但这个程序至少已经关闭了TCP延迟(对于短暂的连接来说它很不合适),同时为外发的文件设置了缓冲。而且更重要的是,所有的线程操作都相互独立。新的连接请求由哪一个线程处理由本机的(因而也是速度较快的)accept()方法决定。除了ServerSocket对象之外,各个线程之间不共享可能需要同步的任何其他资源。这个方案速度较快,但令人遗憾的是,它不具有很好的可伸缩性,其原因就在于,很显然地,线程是一种有限的资源。

  三、非阻塞的HTTP服务器

  下面我们来看看另一个使用非阻塞的新I/O API的方案。新的方案要比原来的方案稍微复杂一点,而且它需要各个线程的协作。它包含下面四个类:

  ·NIOHttpd
  ·Acceptor
  ·Connection
  ·ConnectionSelector


察看评论详细内容 我要发表评论
作者笔名 简短内容 发表时间
:

键盘也能翻页,试试“← →”键

关注我们

最新资讯离线随时看 聊天吐槽赢奖品
闂傚倸鍊搁崐鎼佸磹閹间礁纾瑰瀣捣閻棗霉閿濆牊顏犵紒鈧繝鍌楁斀闁绘ɑ褰冮埀顒€顕槐鎾愁潩鏉堛劌鏋戦梺鍝勫暙閻楀嫰鍩€椤戣法绐旂€殿喕绮欓、姗€鎮欓懠鍨涘亾閸喒鏀介柨娑樺娴犙呯磼椤曞懎鐏︾€殿噮鍋婇幃鈺冪磼濡攱瀚奸梻鍌欑贰閸嬪棝宕戝☉銏″殣妞ゆ牗绋掑▍鐘绘煙缂併垹鏋熼柣鎾寸懄閵囧嫰寮埀顒勵敄濞嗗繄缂氶柟鎵閻撴瑧鈧懓瀚晶妤呭吹閸モ斁鍋撶憴鍕8闁告柨绉堕幑銏犫攽鐎n亞锛滃┑鐐叉閸旀牠鍩㈤弴鐔虹瘈闁汇垽娼у暩濡炪倧缍€濡嫬宓勯梺鍛婄⊕濞兼瑧澹曟繝姘厵闁硅鍔﹂崵娆戠磼閻欌偓閸ㄥ爼寮婚妸鈺傚亞闁稿本绋戦锟�闂傚倸鍊搁崐鎼佸磹閹间礁纾归柣鎴eГ閸婂潡鏌ㄩ弴鐐测偓鍝ョ不閺嶎厽鐓曟い鎰剁稻缁€鈧紒鐐劤濞硷繝寮婚悢鐓庣畾闁绘鐗滃Λ鍕磼閹冣挃缂侇噮鍨抽幑銏犫槈閵忕姷顓哄┑鐐叉缁绘帗绂掓總鍛娾拺闁告繂瀚銉╂煕鎼达絾鏆鐐插暙椤粓鍩€椤掑嫬绠栨繛鍡樻尭缁狙囨煕椤垵鏋ょ憸鐗堝灥閳规垿鎮欓懠顒佹喖缂備緡鍠栫粔鍫曞礆閹烘绠婚悹鍥蔼閹芥洖鈹戦悙鏉戠仧闁糕晛瀚板顐﹀礃椤旂晫鍙嗗┑鐘绘涧濡瑩藟閻樼偨浜滈柨鏂挎惈閸旓附鎱ㄦ繝鍐┿仢鐎规洏鍔嶇换婵嬪礃閻愵剦妫濋梻鍌欒兌閹虫捇宕甸弽顓炵闁跨噦鎷�