ï»??xml version="1.0" encoding="utf-8" standalone="yes"?>黄污视频在线观看 ,噼里啪啦在线中文观看,国产超碰在线一区http://www.aygfsteel.com/shinzey/category/44813.htmlåºæ€hä¸å¿…自扰åQŒæ™ºè€…何需åƒè™‘åQ?/description>zh-cnThu, 16 Feb 2012 11:54:55 GMTThu, 16 Feb 2012 11:54:55 GMT60éžä¸»‹¹åƈå‘工具之 ForkJoinPoolhttp://www.aygfsteel.com/shinzey/archive/2012/02/09/368312.html蜀山兆孨龘蜀山兆孨龘Thu, 09 Feb 2012 02:40:00 GMThttp://www.aygfsteel.com/shinzey/archive/2012/02/09/368312.htmlhttp://www.aygfsteel.com/shinzey/comments/368312.htmlhttp://www.aygfsteel.com/shinzey/archive/2012/02/09/368312.html#Feedback0http://www.aygfsteel.com/shinzey/comments/commentRss/368312.htmlhttp://www.aygfsteel.com/shinzey/services/trackbacks/368312.html

ForkJoinPool æ˜?Java SE 7 新功能“分å?¾l“åˆæ¡†æž¶â€çš„æ ¸å¿ƒ¾c»ï¼ŒçŽ°åœ¨å¯èƒ½ä¹ähé—®æÓ|åQŒä½†æˆ‘觉得它˜qŸæ—©ä¼šæˆä¸ÞZ¸»‹¹ã€‚分å?¾l“åˆæ¡†æž¶æ˜¯ä¸€ä¸ªæ¯”较特ŒDŠçš„¾U¿ç¨‹æ± æ¡†æžÓž¼Œä¸“用于需è¦å°†ä¸€ä¸ªä“QåŠ¡ä¸æ–­åˆ†è§£æˆå­ä“Q务(分å‰åQ‰ï¼Œå†ä¸æ–­è¿›è¡Œæ±‡æ€Õd¾—到最¾lˆç»“果(¾l“åˆåQ‰çš„计算˜q‡ç¨‹ã€‚比起传¾lŸçš„¾U¿ç¨‹æ± ç±» ThreadPoolExecutoråQ?code>ForkJoinPool 实现了工作窃å–算法,使得½Iºé—²¾U¿ç¨‹èƒ½å¤Ÿä¸ÕdŠ¨åˆ†æ‹…ä»Žåˆ«çš„çº¿½E‹åˆ†è§£å‡ºæ¥çš„å­ä“Q务,从而让所有的¾U¿ç¨‹éƒ½å°½å¯èƒ½å¤„于饱满的工作状æ€ï¼Œæé«˜æ‰§è¡Œæ•ˆçއã€?/p>

ForkJoinPool æä¾›äº†ä¸‰¾cÀL–¹æ³•æ¥è°ƒåº¦å­ä“Q务:

execute ¾pÕdˆ—
异步执行指定的ä“Q务ã€?/dd>
invoke å’?invokeAll
执行指定的ä“Q务,½{‰å¾…完æˆåQŒè¿”回结果ã€?/dd>
submit ¾pÕdˆ—
异步执行指定的ä“QåŠ¡åÆˆç«‹å³˜q”回一ä¸?Future 对象ã€?/dd>

å­ä“Q务由 ForkJoinTask 的实例æ¥ä»£è¡¨ã€‚它是一个抽象类åQŒJDK 为我们æä¾›äº†ä¸¤ä¸ªå®žçްåQ?code>RecursiveTask å’?RecursiveActionåQŒåˆ†åˆ«ç”¨äºŽéœ€è¦å’Œä¸éœ€è¦è¿”回计½Ž—结果的å­ä“Q务ã€?code>ForkJoinTask æä¾›äº†ä¸‰ä¸ªé™æ€çš„ invokeAll æ–ÒŽ³•æ¥è°ƒåº¦å­ä»ÕdŠ¡åQŒæ³¨æ„åªèƒ½åœ¨ ForkJoinPool 执行计算的过½E‹ä¸­è°ƒç”¨å®ƒä»¬ã€?/p>

ForkJoinPool å’?ForkJoinTask ˜q˜æä¾›äº†å¾ˆå¤šè®©ähçœÆDб¾~­äؕ的公共方法,其实它们大多数都是其内部实现去调用的åQŒå¯¹äºŽåº”用开å‘äh员æ¥è¯´æ„义ä¸å¤§ã€?/p>

下é¢ä»¥ç»Ÿè®?D 盘文件个æ•îCؓ例。这实际上是对一个文件树的é历,我们需è¦é€’归地统计æ¯ä¸ªç›®å½•下的文件数é‡ï¼Œæœ€åŽæ±‡æ€»ï¼Œéžå¸¸é€‚åˆç”¨åˆ†å?¾l“åˆæ¡†æž¶æ¥å¤„ç†ï¼š

// 处ç†å•个目录的ä“QåŠ?
public class CountingTask extends RecursiveTask<Integer> {
    private Path dir;

    public CountingTask(Path dir) {
        this.dir = dir;
    }

    @Override
    protected Integer compute() {
        int count = 0;
        List<CountingTask> subTasks = new ArrayList<>();

        // è¯Õd–目录 dir çš„å­è·¯å¾„ã€?
        try (DirectoryStream<Path> ds = Files.newDirectoryStream(dir)) {
            for (Path subPath : ds) {
                if (Files.isDirectory(subPath, LinkOption.NOFOLLOW_LINKS)) {
                    // å¯ÒŽ¯ä¸ªå­ç›®å½•都新å»ÞZ¸€ä¸ªå­ä»ÕdŠ¡ã€?
                    subTasks.add(new CountingTask(subPath));
                } else {
                    // é‡åˆ°æ–‡äšgåQŒåˆ™è®¡æ•°å™¨å¢žåŠ?1ã€?
                    count++;
                }
            }

            if (!subTasks.isEmpty()) {
                // 在当å‰çš„ ForkJoinPool 上调度所有的å­ä“Q务ã€?
                for (CountingTask subTask : invokeAll(subTasks)) {
                    count += subTask.join();
                }
            }
        } catch (IOException ex) {
            return 0;
        }
        return count;
    }
}

// 用一ä¸?ForkJoinPool 实例调度“æ€ÖM“Q务â€ï¼Œç„¶åŽæ•¬è¯·æœŸå¾…¾l“果…â€?
Integer count = new ForkJoinPool().invoke(new CountingTask(Paths.get("D:/")));
    

在我的笔记本上,¾l多‹Æ¡è¿è¡Œè¿™ŒDµä»£ç ï¼Œè€—费的时间稳定在 600 豪秒左å³ã€‚普通线½E‹æ± åQ?code>Executors.newCachedThreadPool()åQ‰è€—æ—¶ 1100 毫秒左å³åQŒèƒöè§å·¥ä½œçªƒå–的优势ã€?/p>

¾l“æŸæœ¬æ–‡å‰ï¼Œæˆ‘们æ¥å›´è§‚一个最¼œžå¥‡çš„结果:å•线½E‹ç®—法(使用 Files.walkFileTree(...)åQ‰æ¯”˜q™ä¸¤ä¸ªéƒ½å¿«ï¼Œòq›_‡è€—æ—¶ 550 毫秒åQ这警告我们òq‰™žå¼•入多线½E‹å°±èƒ½ä¼˜åŒ–性能åQŒåƈ™å»è¦å…ˆç»˜q‡å¤š‹Æ¡æµ‹è¯•æ‰èƒ½ä¸‹¾l“论ã€?/p>

]]>
Java ¾|‘络¾~–程从èœé¸Ÿåˆ°å«å…½ 4åQšé¢å‘æµçš„套接字 I/Ohttp://www.aygfsteel.com/shinzey/archive/2012/01/19/368751.html蜀山兆孨龘蜀山兆孨龘Thu, 19 Jan 2012 06:37:00 GMThttp://www.aygfsteel.com/shinzey/archive/2012/01/19/368751.htmlhttp://www.aygfsteel.com/shinzey/comments/368751.htmlhttp://www.aygfsteel.com/shinzey/archive/2012/01/19/368751.html#Feedback0http://www.aygfsteel.com/shinzey/comments/commentRss/368751.htmlhttp://www.aygfsteel.com/shinzey/services/trackbacks/368751.html

å‰é¢å·²ç»çœ‹åˆ°åQ?code>Socket ¾cÈš„ getInputStream() å’?getOutStream() æ–ÒŽ³•分别获å–套接字的输入‹¹å’Œè¾“出‹¹ã€‚输入æµç”¨æ¥è¯Õd–˜qœç«¯å‘é€è¿‡æ¥çš„æ•°æ®åQŒè¾“出æµåˆ™ç”¨æ¥å‘˜qœç«¯å‘逿•°æ®ã€?/p>

输入‹¹?/h1>

使用套接字的输入‹¹è¯»å–æ•°æ®æ—¶åQŒå½“å‰çº¿½E‹ä¼š˜q›å…¥é˜Õd¡žçжæ€ï¼Œç›´åˆ°å¥—接字收åˆîC¸€äº›æ•°æ®äؓ止(亦å³å¥—接字的接收¾~“冲区有å¯ç”¨æ•°æ®åQ‰ã€‚该输入‹¹çš„ available() æ–ÒŽ³•åªæ˜¯˜q”回接收¾~“冲区的å¯ç”¨å­—节数é‡åQŒä¸å¯èƒ½çŸ¥é“˜qœç«¯˜q˜è¦å‘é€å¤šž®‘字节。ä‹É用输入æµçš„æ—¶å€™ï¼Œæœ€å¥½å…ˆž®†å®ƒåŒ…装ä¸ÞZ¸€ä¸?BufferedInputStreamåQŒå› ä¸ø™¯»å–接收缓冲区ž®†å¯¼è‡?JVM 和底层系¾lŸä¹‹é—´çš„切æ¢åQŒåº”当尽é‡å‡ž®‘åˆ‡æ¢æ¬¡æ•îC»¥æé«˜æ€§èƒ½ã€?code>BufferedInputStream çš„ç¼“å†²åŒºå¤§å°æœ€å¥½è®¾ä¸ºå¥—接字接收¾~“冲区的大å°ã€?/p>

如果直接调用输入‹¹çš„ close() æ–ÒŽ³•æ¥å…³é—­å®ƒåQŒåˆ™ž®†å¯¼è‡´å¥—接字被关闭。对此,Socket ¾cÀL供了一ä¸?shutdownInput() æ–ÒŽ³•æ¥ç¦ç”¨è¾“å…¥æµã€‚调用该æ–ÒŽ³•åŽï¼Œæ¯æ¬¡è¯ÀL“作都ž®†è¿”å›?EOFåQŒæ— æ³•å†è¯Õd–˜qœç«¯å‘é€çš„æ•°æ®ã€‚对˜q™ä¸ª EOF 的检‹¹‹ï¼Œä¸åŒçš„输入æµåŒ…装体现å‡ÞZ¸åŒçš„¾l“æžœåQŒå¯èƒ½è¯»åˆ?-1 个字节,å¯èƒ½è¯Õdˆ°çš„å­—½W¦ä¸²ä¸?nullåQŒè¿˜å¯èƒ½æ”¶åˆ°ä¸€ä¸?EOFException ½{‰ç­‰ã€‚ç¦ç”¨è¾“å…¥æµåŽï¼Œ˜qœç«¯è¾“出‹¹çš„è¡ŒäØ“æ˜¯åã^å°ç›¸å…³çš„åQ?/p>

  • åœ?BSD òq›_°ä¸Šï¼Œ˜qœç«¯çš„å‘é€çš„æ•°æ®èƒ½æ­£å¸¸æŽ¥æ”Óž¼Œç„¶åŽç›´æŽ¥ä¸¢å¼ƒã€‚è¿œç«¯æ— æ³•çŸ¥é“æœ¬ç«¯çš„输入‹¹å·²¼›ç”¨ã€‚è¿™å’?JDK 文档æè¿°çš„行ä¸ÞZ¸€è‡´ã€?/li>
  • åœ?WINSOCK òq›_°ä¸Šï¼Œ˜qœç«¯å‘逿•°æ®å°†ä¼šå¯¼è‡´â€œè¿žæŽ¥è¢«é‡ç½®â€çš„错误ã€?/li>
  • åœ?Linux òq›_°ä¸Šï¼Œ˜qœç«¯å‘é€çš„æ•°æ®èƒ½ç‘ô¾l­æŽ¥æ”Óž¼Œç›´åˆ°å¥—接字输入缓冲区填满åQŒä¹‹åŽè¿œç«¯å†ä¹Ÿæ— æ³•å‘逿•°æ®ï¼ˆè‹¥ä‹É用阻塞模å¼åˆ™˜q›å…¥æ­»é”åQ‰ã€?/li>

¼›ç”¨è¾“å…¥‹¹è¿™¿UæŠ€æœ¯åÆˆä¸å¸¸ç”¨ã€?/p>

输出‹¹?/h1>

套接字的输出æ“作实际上仅仅将数æ®å†™åˆ°å‘é€ç¼“冲区内,当å‘é€ç¼“冲区填满且上‹Æ¡çš„å‘逿ˆåŠŸåŽåQŒç”±åº•层¾pÈ»Ÿè´Ÿè´£å‘é€ã€‚如果å‘é€ç¼“冲区的剩余空间ä¸å¤Ÿï¼Œå½“剾U¿ç¨‹ž®×ƒ¼šé˜Õd¡žã€‚和输入‹¹ç±»ä¼û|¼Œæœ€å¥½å°†è¾“出‹¹åŒ…è£…äØ“ BufferedOutputStreamã€?/p>

如果套接字的åŒå‘都ä‹Éç”?ObjectInputStream å’?ObjectOutputStream æ¥è¯»å†?Java 对象åQŒåˆ™å¿…须先创å»?ObjectOutputStreamåQŒå› ä¸?ObjectInputStream 在构造的时候会试图è¯Õd–对象头部åQŒå¦‚æžœåŒå‘都先创å»?ObjectInputStreamåQŒåˆ™ä¼šäº’相等待对方的输出åQŒé€ æˆæ­»é”åQ?/p>

// 创å¾çš„顺åºä¸èƒ½é¢ å€’ï¼
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
    

¾cÖM¼¼äºŽè¾“å…¥æµåQŒå…³é—­è¾“出æµä¹Ÿå¯¼è‡´å…³é—­å¥—接字åQŒæ‰€ä»?Socket ¾cÕdŒæ äh供了一ä¸?shutdownOutput() æ¥ç¦ç”¨è¾“出æµã€‚ç¦ç”¨è¾“出æµåŽï¼Œå·²å†™å…¥å‘é€ç¼“冲区的数æ®ä¼šæ­£å¸¸å‘é€ï¼Œä¹‹åŽçš„ä“Q何写æ“ä½œéƒ½ä¼šå¯ÆD‡´ IOExceptionåQŒä¸”˜qœç«¯çš„输入æµå§‹ç»ˆä¼šè¯»åˆ?EOF。ç¦ç”¨è¾“出æµéžå¸¸æœ‰ç”¨åQŒä¾‹å¦‚套接字的åŒå‘都在å‘é€å®Œæ¯•æ•°æ®å޼›ç”¨è¾“å…¥‹¹ï¼Œç„¶åŽåŒæ–¹éƒ½ä¼šæ”¶åˆ° EOFåQŒä»Žè€ŒçŸ¥é“æ•°æ®å·²¾l全部交æ¢å®Œæ¯•,å¯ä»¥å®‰å…¨å…³é—­å¥—æŽ¥å­—ã€‚ç›´æŽ¥å…³é—­å¥—æŽ¥å­—ä¼šåŒæ—¶å…³é—­è¾“å…¥æµå’Œè¾“出æµåQŒä¸”æ–­å¼€˜qžæŽ¥åQŒè¾¾ä¸åˆ°˜q™ç§æ•ˆæžœã€?/p>

使用‹¹çš„é˜Õd¡žå¥—接字的优缺ç‚?/h2>

如果è¦ä‹É用浘q›è¡Œè¾“入和输出,ž®±åªèƒ½ç”¨é˜Õd¡žæ¨¡å¼çš„套接字。这里æ€È»“一下阻塞套接字的优¾~ºç‚¹ã€‚先看看优点åQ?/p>

  1. ¾~–程模型½Ž€å•,éžå¸¸é€‚åˆåˆå­¦è€…上手ã€?/li>
  2. 以装饰器模å¼è®¾è®¡çš?Java I/O 使得开å‘äh员å¯ä»¥è½»æ‘Öœ°ä»?I/O ‹¹è¯»å†™ä“Q何类型的数æ®ã€?/li>

但在性能斚w¢æœ‰è‡´å‘½çš„¾~ºç‚¹åQ?/p>

  1. ç”׃ºŽæœåŠ¡å™¨å¥—æŽ¥å­—æŽ¥å—˜qžæŽ¥åQŒä»¥åŠå¥—接字的读写都会阻塞,性能低下ã€?/li>
  2. 如果ä¸å¯¹ I/O ‹¹æ‰‹åŠ¨è¿›è¡Œç¼“å†ÔŒ¼Œåˆ™å¯èƒ½é€ æˆä¸€‹Æ¡åªå¤„ç†ä¸€ä¸ªå­—节,性能低下ã€?/li>
  3. æœåŠ¡å™¨å¥—æŽ¥å­—æ¯æ¬¡åªèƒ½æŽ¥å—ä¸€ä¸ªè¿žæŽ¥ï¼Œå¯ÆD‡´ JVM 和底层系¾lŸä¹‹é—´é¢‘¾J的调用切æ¢åQŒæ€§èƒ½ä½Žä¸‹ã€?/li>

下一½‹‡æ–‡ç« å¼€å§‹æŽ¢è®¨ä‹É用基äº?NIO 的套接字通é“和缓冲区实现伸羃性更强的 TCP 套接字ã€?/p>

]]>Java ¾|‘络¾~–程从èœé¸Ÿåˆ°å«å…½ 3åQšå¥—接字åˆå§‹åŒ–详è§?/title><link>http://www.aygfsteel.com/shinzey/archive/2012/01/16/368393.html</link><dc:creator>蜀山兆孨龘</dc:creator><author>蜀山兆孨龘</author><pubDate>Mon, 16 Jan 2012 02:31:00 GMT</pubDate><guid>http://www.aygfsteel.com/shinzey/archive/2012/01/16/368393.html</guid><wfw:comment>http://www.aygfsteel.com/shinzey/comments/368393.html</wfw:comment><comments>http://www.aygfsteel.com/shinzey/archive/2012/01/16/368393.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.aygfsteel.com/shinzey/comments/commentRss/368393.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/shinzey/services/trackbacks/368393.html</trackback:ping><description><![CDATA[<div id="wmqeeuq" class="article"> <p><code>ServerSocket</code> ¾cÕd’Œ <code>Socket</code> ¾c»éƒ½æä¾›äº†å¤šä¸ªå…¬å…±æž„造方法。ä¸åŒçš„æž„造方法ä¸ä»…å¸¦çš„å‚æ•îC¸åŒï¼Œæ‰€å…ähœ‰çš„æ„ä¹‰ä¹Ÿä¸ä¸€æ —÷€‚下é¢åˆ†åˆ«è§£æžè¿™ä¸¤ä¸ª¾cÈš„实例åˆå§‹åŒ–过½E‹ã€?/p> <h1><code>ServerSocket</code> 实例的åˆå§‹åŒ–</h1> <p><code>ServerSocket</code> ¾cÀL供了四个构造器åQ?/p> <dl> <dt><code>public ServerSocket(int port) throws IOException</code></dt> <dt><code>public ServerSocket(int port, int backlog) throws IOException</code></dt> <dt><code>public ServerSocket(int port, int backlog, InetAddress bindAddr) throws IOException</code></dt> <dt><code>public ServerSocket() throws IOException</code></dt> </dl> <p>另傿ž„造器用æ¥åˆ›å¾å·²ç»‘定的æœåŠ¡å™¨å¥—æŽ¥å­—åQŒä¹Ÿž®±æ˜¯è¯´æž„造æˆåŠŸåŽå®ƒå°±å·²ç»å¼€å§‹ä¾¦å¬æŒ‡å®šçš„端å£åQŒä¸”能够调用 <code>accept()</code> æ–ÒŽ³•æ¥æŽ¥å—客æˆïL«¯˜qžæŽ¥ã€‚é»˜è®¤æž„é€ å™¨åˆ™ä¼šåˆ›å¾æœªç»‘定的æœåŠ¡å™¨å¥—æŽ¥å­—åQŒæž„造æˆåŠŸåŽå¿…须手动ž®†å…¶¾l‘定åˆîC¸€ä¸ªæœ¬åœ°åœ°å€æ‰èƒ½ç”¨ï¼Œåœ¨ç»‘定之å‰å¯ä»¥è¿›è¡Œä¸€äº›é€‰é¡¹é…ç½®ã€?/p> <h2>另傿ž„造器</h2> <p>æ€Èš„æ¥è¯´åQŒå¸¦å‚构造器æä¾›äº†ä¸‰ä¸ªå‚敎ͼš</p> <dl> <dt><code>port</code></dt> <dd>指定该æœåŠ¡å™¨å¥—æŽ¥å­—æ‰€è¦ä¾¦å¬çš„æœ¬åœ°ç«¯å£ã€‚å¦‚æžœäØ“ 0åQŒåˆ™ç”Þq³»¾lŸè‡ªåŠ¨åˆ†é…一个端å£å·åQŒè¿™å¿…须以å¦å¤–的方å¼è®©å®¢æˆïL«¯èŽ·å–端å£å—÷€?/dd> <dt><code>backlog</code></dt> <dd>˜q™ä¸ªåè¯ç›®å‰˜q˜æ²¡æœ‰åˆé€‚的译å。底层系¾lŸçš„ TCP 实现会维护一个连接队列,该队列缓存了已被 TCP 处ç†å®Œæ¯•åQŒä½†˜q˜æ²¡æœ‰è¢«æœåŠ¡å™¨å¥—æŽ¥å­—æŽ¥å—的客æˆïL«¯˜qžæŽ¥ã€‚一旦æŸä¸ªè¿žæŽ¥è¢«æŽ¥å—åQˆé€šè¿‡è°ƒç”¨ <code>accept()</code> æ–ÒŽ³•åQ‰ï¼Œå®ƒå°±ä¼šè¢«ä»Žé˜Ÿåˆ—中¿U»é™¤ã€?code>backlog</code> 傿•°ž®Þq”¨äºŽæŒ‡å®šé˜Ÿåˆ—的最大长度,默认å€égØ“ 50åQŒä½†˜q™ä¸ªå€¼åªæ˜¯ä¸€ä¸ªå¾è®®ï¼Œåº•层¾pÈ»Ÿå¯èƒ½æ ÒŽ®éœ€è¦è‡ªåŠ¨è°ƒæ•´ã€‚å¦‚æžœé˜Ÿåˆ—æ»¡äº†ï¼Œåˆ™å…¶è¡ŒäØ“æ˜¯åã^å°ç›¸å…³çš„åQšå¾®è½¯çš„ WINSOCK 会拒¾l新的连接,其他实现则什么都ä¸åšã€‚严格地è¯ß_¼Œå¾®èÊY没有éµå®ˆè§„范åQŒç ´å了游æˆè§„则…â€?/dd> <dt><code>bindAddr</code></dt> <dd>䏀尿œºå™¨å¯èƒ½ä¼šæœ‰å¤šä¸ªæœ¬åœ?IP 地å€åQŒä¾‹å¦‚åŒæ—¶ä‹É用多å—网å¡ã€‚ä‹Éç”¨å…¶ä»–ä¸¤ä¸ªå¸¦å‚æž„造器æ—Óž¼Œè¯¥å‚æ•îCØ“ <code>null</code>åQŒæœåŠ¡å™¨å¥—æŽ¥å­—ä¼šåœ¨æ‰€æœ‰çš„æœ¬åœ° IP 地å€åQ?code>0.0.0.0</code> æˆ?<code>::0</code>åQ‰ä¸Šä¾¦å¬ã€‚如果希望åªä¾¦å¬ä¸€ä¸ªåœ°å€åQŒåˆ™å¯ä‹Éç”¨è¯¥å‚æ•°ã€?/dd> </dl> <h2>默认构造器</h2> <p>如果使用默认构造器åQŒåœ¨¾l‘定地å€å‰ï¼Œ˜q˜å¯ä»¥åšäº›é…¾|®ã€‚绑定æ“作由两个 <code>bind</code> æ–ÒŽ³•定义åQŒå‚æ•°ç±»ä¼égºŽå¸¦å‚构造器。酾|®é¡¹åŒ…括以下斚w¢åQˆéƒ½å¿…须在绑定å‰é…ç½®åQ‰ï¼š</p> <dl> <dt>讄¡½®æ˜¯å¦é‡ç”¨æœ¬åœ°åœ°å€</dt> <dd>该选项ç”?<code>setReuseAddress(boolean on)</code> æ–ÒŽ³•é…ç½®åQŒå¯¹åº”底层系¾lŸçš„ <code>SO_REUSEADDR</code> 套接字选项。JDK 没有定义该选项的默认倹{€‚如果该选项ä¸?<code>false</code>åQŒåˆ™åœ¨å…³é—?TCP ˜qžæŽ¥æ—Óž¼Œä¸ÞZº†ä¿è¯å¯é æ€§ï¼Œè¯¥è¿žæŽ¥å¯èƒ½åœ¨å…³é—­åŽçš„一ŒD‰|—¶é—ß_¼ˆå¤§çº¦ä¸¤åˆ†é’Ÿï¼‰å†…ä¿æŒè¶…时状æ€ï¼ˆé€šå¸¸¿UîCØ“ <code>TIME_WAIT</code> çŠ¶æ€æˆ– <code>2MSL</code> ½{‰å¾…状æ€ï¼‰åQŒè¿™ŒD‰|—¶é—´é‡Œæ— æ³•ž®†æ–°å»ºçš„æœåŠ¡å™¨å¥—æŽ¥å­—¾l‘定到åŒä¸€ä¸ªåœ°å€ã€‚在开å‘阶ŒDµï¼ŒæœåС噍å¯èƒ½ä¸æ–­é‡å¯ï¼Œæ‰“开攚w€‰é¡¹ä¼šéžå¸¸æœ‰ç”¨ã€?/dd> <dt>讄¡½®æŽ¥æ”¶¾~“冲区大ž®?/dt> <dd>该选项ç”?<code>setReceiveBufferSize(int size)</code> æ–ÒŽ³•é…ç½®åQŒå¯¹åº”底层系¾lŸçš„ <code>SO_RCVBUF</code> 套接字选项åQŒå•使˜¯å­—节。《RFC 1323 - TCP Extensions for High Performance》将¾~“冲区大ž®å®šä¹‰äØ“ 64KBã€‚è¯¥é€‰é¡¹åªæ˜¯ä¸€ä¸ªå¾è®®å€û|¼Œåº•层¾pÈ»Ÿå¯èƒ½æ ÒŽ®éœ€è¦è‡ªè¡Œè°ƒæ•´ã€?/dd> <dt>讄¡½®­‘…æ—¶å€?/dt> <dd>该选项ç”?<code>setSoTimeout(int timeout)</code> æ–ÒŽ³•é…ç½®åQŒå¯¹åº”底层系¾lŸçš„ <code>SO_TIMEOUT</code> 套接字选项åQŒå•使˜¯æ¯«ç§’。默认å€égØ“ 0ã€‚è¯¥é€‰é¡¹å½±å“ <code>accept</code> æ–ÒŽ³•的阻塞时间长度,如果­‘…æ—¶ž®†å¼•å?<code>SocketTimeoutException</code>。如果设ä¸?0åQŒåˆ™è¡¨ç¤ºæ°æ€¸­‘…æ—¶ã€?/dd> <dt>讄¡½®æ€§èƒ½é¦–选项</dt> <dd>性能首选项包括˜qžæŽ¥æ—‰™—´ã€åšg˜qŸå’Œå¸¦å®½ä¸‰ä¸ªé€‰é¡¹åQŒç”± <code>setPerformancePreferences(int connectionTime, int latency, int bandwidth) </code> æ–ÒŽ³•é…置。这三个数值分别表½CºçŸ­˜qžæŽ¥æ—‰™—´ã€ä½Žå»¶è¿Ÿå’Œé«˜å¸¦å®½çš„相寚w‡è¦æ€§ï¼Œæ•°å€ÆD¶Šå¤§åˆ™­‘Šé‡è¦ï¼›å…¶å„自的¾l对值没有æ„义。该æ–ÒŽ³•çš„åˆè¡äh˜¯ä¸ÞZº†è®?Java èƒ½åœ¨ç”¨éž TCP/IP 实现的套接字环境下工作得更好åQŒæŸäº›éœ€è¦å¯¹¾|‘络˜q›è¡Œè°ƒä¼˜çš„程åºä¹Ÿå¯ä»¥ž®†è¿™ä¸‰ä¸ªé¦–é€‰é¡¹ä½œäØ“é…ç½®å‚æ•°æä¾›¾l™ç”¨æˆ—÷€?/dd> </dl> <h1><code>Socket</code> 实例的åˆå§‹åŒ–</h1> <p><code>Socket</code> ¾cÀL供了六个公共构造器åQˆå·²˜q‡æ—¶çš„除外)åQ?/p> <dl> <dt><code>public Socket(String host, int port) throws UnknownHostException, IOException</code></dt> <dt><code>public Socket(InetAddress address, int port) throws IOException</code></dt> <dt><code>public Socket(String host, int port, InetAddress localAddr, int localPort) throws IOException</code></dt> <dt><code>public Socket(InetAddress address, int port, InetAddress localAddr, int localPort) throws IOException</code></dt> <dt><code>public Socket()</code></dt> <dt><code>public Socket(Proxy proxy)</code></dt> </dl> <p>å‰å››ä¸ªæž„造器创å¾å·²è¿žæŽ¥çš„客户端套接字åQŒä¹Ÿž®±æ˜¯è¯´æž„造的时候就会去˜qžæŽ¥æœåŠ¡å™¨ã€‚å‰ä¸¤ä¸ªæž„é€ å™¨éœ€è¦æä¾›æœåŠ¡å™¨çš„åœ°å€å’Œç«¯å£ä½œä¸ºå‚敎ͼŒæœ¬åœ°åœ°å€å’Œç«¯å£ç”±¾pÈ»Ÿè‡ªåŠ¨åˆ†é…åQ›åŽä¸¤ä¸ªå…许手动指定本地地å€å’Œç«¯å£ï¼Œä½†æžž®‘ä‹É用。åŽä¸¤ä¸ªæž„é€ å™¨åˆ›å¾æœªè¿žæŽ¥çš„套接字,创å¾åŽéœ€è¦è°ƒç”?<code>connect</code> æ–ÒŽ³•手动˜qžæŽ¥åQŒè¿žæŽ¥ä¹‹å‰å¯ä»¥åšä¸€äº›é…¾|®ã€‚最åŽä¸€ä¸ªæž„造器接å—ä¸€ä¸ªä»£è¡¨ä»£ç†æœåС其çš?<code>Proxy</code> 对象åQŒJDK æ”¯æŒ HTTP å’?SOCKSåQˆV4 æˆ?V5åQ‰ä¸¤¿U代ç†ç±»åž‹ã€?/p> <h2>˜qžæŽ¥å‰çš„é…ç½®</h2> <p>在连接å‰åQŒå®¢æˆïL«¯å¥—接字ä¸ä»…åƒæœåŠ¡å™¨å¥—æŽ¥å­—é‚£æ ·å¯ä»¥è®„¡½®æ˜¯å¦é‡ç”¨æœ¬åœ°åœ°å€ã€ç¼“冲区大å°ã€è¶…时值和性能首选项åQŒè¿˜èƒ½å¤Ÿé…置以下å„项åQˆéƒ½å¿…须在连接å‰é…ç½®åQ‰ï¼š</p> <dl> <dt>讄¡½®æ˜¯å¦ä¿æŒ‹z»è·ƒ</dt> <dd>该选项ç”?<code>setKeepAlive(boolean on)</code> æ–ÒŽ³•é…ç½®åQŒå¯¹åº”底层系¾lŸçš„ <code>SO_KEEPALIVE</code> 套接字选项。默认å€égØ“ <code>false</code>。如果打开该选项åQŒåˆ™å¥—接字会定期自动å‘é€ä¿æŒæ´»è·ƒçš„æŽ¢æµ‹æ€§æ¶ˆæ¯ï¼Œ¾cÖM¼¼äºŽå¿ƒè·Ïx£€‹¹‹ã€‚æ ¹æ®ã€ŠRFC 1122 - Requirements for Internet Hosts》的规定åQŒä¿æŒæ´»è·ƒæœºåˆ¶åªæ˜?TCP 的一个å¯é€‰åŠŸèƒ½ï¼Œå¦‚æžœæ”¯æŒçš„è¯åQŒé»˜è®¤å¿…™åÖMØ“ <code>false</code>åQŒè€Œä¸”˜q™ç§æœºåˆ¶é»˜è®¤åœ¨æˆåŠŸå¾ç«‹è¿žæŽ¥åŽåQŒä¸”˜qžç®‹ä¸¤å°æ—¶æ²¡æœ‰æ•°æ®ä¼ è¾“的情况下æ‰ä¼šè¢«‹È€‹z…R€‚从å¦ä¸€æ–šw¢æ¥çœ‹åQŒé€šè¿‡å¥—接字的 I/O æ“作完全å¯ä»¥çŸ¥é“˜qžæŽ¥æ˜¯å¦˜q˜æœ‰æ•ˆï¼Œæ‰€ä»¥è¯¥é€‰é¡¹çš„实用ä­hå€ég¸å¤§ã€?/dd> <dt>讄¡½®æ˜¯å¦æ”¶å‘带外数æ®</dt> <dl>该选项ç”?<code>setOOBInline(boolean on)</code> æ–ÒŽ³•é…ç½®åQŒå¯¹åº”底层系¾lŸçš„ <code>SO_OOBINLINE</code> 套接字选项。默认å€égØ“ <code>off</code>。带外数æ®ï¼ˆOut-of-band DataåQ‰ä¹Ÿå«åšç´§æ€¥æ•°æ®ï¼Œè¡¨ç¤ºæ•°æ®å¾ˆé‡è¦ï¼Œéœ€è¦ä‹É用ä¸åŒäºŽå‘逿™®é€šæ•°æ®çš„ä¸€ä¸ªä¸“ç”¨é€šé“æ¥å‘é€ã€‚打开该选项åŽï¼Œž®±å¯ä»¥è°ƒç”?<code>sendUrgentData(int data)</code> æ–ÒŽ³•å‘é€ä¸€ä¸ªå­—节的紧急数æ®ã€‚JDK 对带外数æ®åªæä¾›äº†æœ‰é™æ”¯æŒï¼Œç´§æ€¥æ•°æ®å°†ä¼šå’Œæ™®é€šæ•°æ®ä¸€èµ¯‚¢«æ”¶åˆ°åQŒåƈ且无法自动区分。该选项对应用开å‘äh员æ„义ä¸å¤§ã€?/dl> <dt>讄¡½®æ˜¯å¦ä»Žå®¹å…³é—­˜qžæŽ¥</dt> <dd>该选项ç”?<code>setSoLinger(boolean on, int linger)</code> æ–ÒŽ³•é…ç½®åQŒå¯¹åº”底层系¾lŸçš„ <code>SO_LINGER</code> å¥—æŽ¥å­—é€‰é¡¹ã€‚é»˜è®¤äØ“ <code>false</code>。该选项åªä¼šå½±å“套接字的关闭åQŒå…¶ä¸­çš„ <code>linger</code> 傿•°è¡¨ç¤º­‘…æ—¶æ—‰™—´åQŒå•ä½äØ“¿U’。如果打开攚w€‰é¡¹åQšå¦‚果将 <code>linger</code> è®¾äØ“ 0åQŒåˆ™å…³é—­å¥—接字的时候,未å‘é€çš„æ•°æ®ä¼šè¢«ä¸¢å¼ƒåQŒä¸”å¦ä¸€ç«¯ä¼šå‡ºçް˜qžæŽ¥è¢«åŒä½ä½“é‡ç½®çš„异常;如果 <code>linger</code> é?0åQŒåˆ™å…³é—­å¥—接字的¾U¿ç¨‹ž®†è¢«é˜Õd¡žåQŒç›´åˆ°æ•°æ®å…¨éƒ¨å‘逿ˆ–­‘…æ—¶åQŒè¶…æ—¶åŽçš„行ä¸ÞZ¸Žåº•层¾pÈ»Ÿç›¸å…³åQŒJDK 无法控制。如果关闭该选项åQŒåˆ™å¥—接字正常关闭,数æ®ä¹Ÿä¼šå…¨éƒ¨å‘é€ã€‚ç”±äºŽåº•å±‚å®žçŽ°çš„å·®å¼‚æ€§ï¼Œä¸æå€¡åº”ç”¨å¼€å‘äh员打开该选项ã€?/dd> <dt>讄¡½®æ˜¯å¦å»¶è¿Ÿå‘逿•°æ?/dt> <dd>该选项ç”?<code>setTcpNoDelay(boolean on)</code> æ–ÒŽ³•é…ç½®åQŒå¯¹åº”底层系¾lŸçš„ <code>TCP_NODELAY</code> TCP 选项。默认å€égØ“ <code>off</code>。打开该选项ž®†ç¦ç”?Nagle ½Ž—法åQŒTCP 包会立å³å‘é€ï¼›å…³é—­è¯¥é€‰é¡¹åˆ™ä¼šå¯ç”¨ Nagle ½Ž—法åQŒå¤šä¸ªè¾ƒž®çš„ TCP åŒ…ä¼šè¢«ç»„åˆæˆä¸€ä¸ªå¤§åŒ…一起å‘é€ï¼Œè™½ç„¶å‘é€åšg˜qŸäº†åQŒä½†æœ‰åˆ©äºŽé¿å…网¾lœæ‹¥å¡žã€‚é»˜è®¤äØ“ <code>false</code>。该选项对实时性很强的½E‹åºå¯èƒ½æœ‰ç”¨åQŒä½†ä¸€èˆ¬çš„½E‹åºä¸éœ€è¦å…³å¿ƒã€?/dd> <dt>讄¡½®‹¹é‡¾cÕdˆ«</dt> <dd>该选项ç”?<code>setTrafficClass(int tc)</code> æ–ÒŽ³•é…ç½®åQŒå¯¹åº”底层系¾lŸçš„“æµé‡ç±»åˆ«â€å¥—接字属性。该选项用于å‘网¾lœï¼ˆä¾‹å¦‚路由器)æç¤ºä»Žè¯¥å¥—接字å‘é€çš„包需è¦èŽ·å–哪些æœåŠ¡ç±»åž‹ï¼Œå¯ÒŽœ¬åœ?TCP å议栈没有媄å“。IPv4 å’?IPv6 分别定义了多个ä¸åŒçš„å€û|¼Œä¾‹å¦‚ IPv4 ž®?<code>0x08</code> 定义为最大åžåé‡åQ?code>0x10</code> 定义为最ž®åšg˜qŸï¼Œ½{‰ç­‰ã€‚å¯ä»¥ç”¨æˆ–è¿½Ž—å°†å¤šä¸ªå€¼åˆòq¶äؓ一个选项。该选项用æ¥è°ƒæ•´æ€§èƒ½åQŒéœ€è¦æ ¹æ®å®žé™…情况设¾|®ã€‚ç”±äºŽåªæ˜¯å¾è®®å€û|¼Œå¯èƒ½è¢«ç½‘¾lœå¿½ç•¥ã€?/dd> </dl> </div><img src ="http://www.aygfsteel.com/shinzey/aggbug/368393.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/shinzey/" target="_blank">蜀山兆孨龘</a> 2012-01-16 10:31 <a href="http://www.aygfsteel.com/shinzey/archive/2012/01/16/368393.html#Feedback" target="_blank" style="text-decoration:none;">å‘表评论</a></div>]]></description></item><item><title>å•例模å¼çš„一个疑é—?/title><link>http://www.aygfsteel.com/shinzey/archive/2012/01/10/368251.html</link><dc:creator>蜀山兆孨龘</dc:creator><author>蜀山兆孨龘</author><pubDate>Tue, 10 Jan 2012 09:39:00 GMT</pubDate><guid>http://www.aygfsteel.com/shinzey/archive/2012/01/10/368251.html</guid><wfw:comment>http://www.aygfsteel.com/shinzey/comments/368251.html</wfw:comment><comments>http://www.aygfsteel.com/shinzey/archive/2012/01/10/368251.html#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://www.aygfsteel.com/shinzey/comments/commentRss/368251.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/shinzey/services/trackbacks/368251.html</trackback:ping><description><![CDATA[<div id="wmqeeuq" class="article"> <p>¾|‘上很多关于å•例模å¼å†™æ³•的文章,ä¸å¤–乎饿汉和懒汉两ç§å½¢å¼çš„讨论。很多äh喜欢用懒汉å¼åQŒå› ä¸ø™§‰å¾—它实现了åšg˜qŸåŠ è½½ï¼Œå¯ä»¥è®©ç³»¾lŸçš„æ€§èƒ½æ›´å¥½ã€‚但事实果真如此å—?我对此存疑ã€?/p> <p>首先我们‹‚€æŸ¥ä¸€ä¸‹é¥¿æ±‰å’Œæ‡’汉å•ä¾‹æ¨¡å¼æœ€½Ž€å•的写法åQˆè¿™é‡Œä¸è®¨è®ºå“ªç§æ‡’汉写法更好åQ‰ï¼š</p> <pre class="brush: java"> // 饿汉 public final class HungrySingleton { private static final HungrySingleton INSTANCE = new HungrySingleton(); private HungrySingleton() { System.out.println("Initializing..."); } public static HungrySingleton getInstance() { return INSTANCE; } } // 懒汉 public final class LazySingleton { private static LazySingleton INSTANCE; private LazySingleton() { System.out.println("Initializing..."); } public static synchronized LazySingleton getInstance() { if (INSTANCE == null) { INSTANCE = new LazySingleton(); } return INSTANCE; } } </pre> <p>从ç†è®ÞZ¸Šæ¥è¯´åQ?code>HungrySingleton</code> çš„å•例在该类½W¬ä¸€‹Æ¡ä‹É用的时候创建,è€?<code>LazySingleton</code> çš„å•例则在其 <code>getInstance()</code> æ–ÒŽ³•被调用的时候创建。至于网上有人声¿U°â€œé¥¿æ±‰å¼ä¸ç®¡ç”¨ä¸ç”¨éƒ½ä¼šåˆå§‹åŒ–â€ï¼Œ¾U¯å±žèµ°èµ\的时候步å­è¿ˆå¾—太大。è°çš„加载更˜qŸï¼Ÿå¦‚æžœä½ åªæ˜¯è°ƒç”¨å®ƒä»¬çš„ <code>getInstance()</code> æ–ÒŽ³•æ¥å¾—到å•例对象,则它们都是åšg˜qŸåŠ è½½ï¼Œ˜q™æ ·æ‡’æ±‰å¼æ²¡æœ‰ä“Q何æ„义,而且ç”׃ºŽ <code>LazySingleton</code> 采å–äº†åŒæ­¥æŽªæ–½ï¼Œæ€§èƒ½æ›´ä½ŽåQˆå¯ä»¥è¯´ä»ÖM½•懒汉å¼çš„æ€§èƒ½éƒ½ä½ŽäºŽé¥¿æ±‰å¼åQ‰ã€‚当你ä‹É用一个å•例类的时候,éšùN“½W¬ä¸€æ­¥ä¸æ˜¯è°ƒç”?<code>getInstance()</code> 么?所以在自己的代ç é‡ŒåQŒæˆ‘æ›´å–œ‹Æ¢ç”¨é¥¿æ±‰å¼ã€?/p> <p>下é¢ç”¨ä¸€ä¸ªä¾‹å­æ¥‹¹‹è¯•加貙åºåºåQ?/p> <pre class="brush: java"> // 饿汉 System.out.println("Before"); HungrySingleton.getInstance(); System.out.println("After"); // 懒汉 System.out.println("Before"); LazySingleton.getInstance(); System.out.println("After"); </pre> <p>输出¾l“果都是åQ?/p> <pre class="output">Before Initializing... After</pre> <p>那么åQŒæ‡’汉模å¼è¿˜æœ‰ä»€ä¹ˆå­˜åœ¨æ„义?如果¾pÈ»Ÿä½¿ç”¨äº†æŸäº›éœ€è¦åœ¨å¯åŠ¨æ—¶å¯¹¾c»è¿›è¡Œæ‰«æçš„æ¡†æž¶åQŒä‹É用饿汉å¼çš„è¯åQŒå¯åŠ¨æ—¶é—´æ¯”æ‡’æ±‰å¼æ›´é•¿ï¼Œå¦‚果使用了大é‡å•例类åQŒä¸åˆ©äºŽå¼€å‘阶ŒDüc€‚在¾pÈ»Ÿçš„æ­£å¼è¿è¡Œé˜¶ŒDµï¼Œæ‰€æœ‰çš„å•例¾c»è¿Ÿæ—©éƒ½è¦åŠ è½½çš„åQŒæ€Èš„说æ¥ä¸¤è€…性能æŒåã^åQŒä½†æ˜¯æ‡’æ±‰å¼æ¯æ¬¡éƒ½è‡³ž®‘å¤šä¸€ä¸ªåˆ¤æ–­ï¼Œæ‰€ä»¥è¶Šåˆ°åŽæœŸè¶Šä½“现饿汉的优­‘Šæ€§ã€?/p> <p>最åŽï¼ŒæŽ¨è下《Effective Java》第二版指出的用枚ä‹D¾cÕdž‹å®žçŽ°çš„é¥¿æ±‰å•例模å¼ï¼š</p> <pre class="brush: java"> // 饿汉 public enum HungrySingleton { INSTANCE; private HungrySingleton() { } } </pre> <p>˜q™ç§å†™æ³•ä¸ä½†æœ€½Ž€‹z,˜q˜èƒ½è½ÀL˜“扩展为实例数é‡å›ºå®šçš„“多例模å¼â€ã€?/p> </div><img src ="http://www.aygfsteel.com/shinzey/aggbug/368251.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/shinzey/" target="_blank">蜀山兆孨龘</a> 2012-01-10 17:39 <a href="http://www.aygfsteel.com/shinzey/archive/2012/01/10/368251.html#Feedback" target="_blank" style="text-decoration:none;">å‘表评论</a></div>]]></description></item><item><title>Java ¾|‘络¾~–程从èœé¸Ÿåˆ°å«å…½ 2åQšTCP 和套接字入门http://www.aygfsteel.com/shinzey/archive/2012/01/04/367846.html蜀山兆孨龘蜀山兆孨龘Wed, 04 Jan 2012 14:21:00 GMThttp://www.aygfsteel.com/shinzey/archive/2012/01/04/367846.htmlhttp://www.aygfsteel.com/shinzey/comments/367846.htmlhttp://www.aygfsteel.com/shinzey/archive/2012/01/04/367846.html#Feedback5http://www.aygfsteel.com/shinzey/comments/commentRss/367846.htmlhttp://www.aygfsteel.com/shinzey/services/trackbacks/367846.html

JDK æä¾›äº†å¯¹ TCPåQˆTransmission Control ProtocolåQŒä¼ è¾“控制å议)å’?UDPåQˆUser Datagram ProtocolåQŒç”¨æˆäh•°æ®æŠ¥åè®®åQ‰è¿™ä¸¤ä¸ªæ•°æ®ä¼ è¾“å议的支æŒã€‚本文开始探è®?TCPã€?/p>

TCP 基础知识

在“æœåС噍-客户端â€è¿™¿U架构中åQŒæœåŠ¡å™¨å’Œå®¢æˆïL«¯å„自¾l´æŠ¤ä¸€ä¸ªç«¯ç‚¹ï¼Œä¸¤ä¸ªç«¯ç‚¹éœ€è¦é€šè¿‡¾|‘络˜q›è¡Œæ•°æ®äº¤æ¢ã€‚TCP 䏸™¿™¿U需求æä¾›äº†ä¸€¿Uå¯é çš„‹¹å¼˜qžæŽ¥åQŒæµå¼çš„æ„æ€æ˜¯ä¼ å‡ºå’Œæ”¶åˆ°çš„æ•°æ®éƒ½æ˜¯˜qžç®‹çš„字节,没有å¯ÒŽ•°æ®é‡˜q›è¡Œå¤§å°é™åˆ¶ã€‚一个端点由 IP 地å€å’Œç«¯å£æž„æˆï¼ˆä¸“业术语为“元¾l?{IP 地å€, 端å£}â€ï¼‰ã€‚è¿™æ øP¼Œä¸€ä¸ªè¿žæŽ¥å°±å¯ä»¥ç”±å…ƒ¾l?{本地地å€, 本地端å£, ˜qœç¨‹åœ°å€, ˜qœç¨‹ç«¯å£} æ¥è¡¨½Cºã€?/p>

˜qžæŽ¥˜q‡ç¨‹

åœ?TCP ¾~–程接å£ä¸­ï¼Œç«¯ç‚¹ä½“现ä¸?TCP 套接字。共有两¿U?TCP 套接字:ä¸ÕdŠ¨å’Œè¢«åŠ¨ï¼Œâ€œè¢«åŠ¨â€çжæ€ä¹Ÿå¸¸è¢«¿UîCؓ“侦å¬â€çжæ€ã€‚æœåŠ¡å™¨å’Œå®¢æˆïL«¯åˆ©ç”¨å¥—接字进行连接的˜q‡ç¨‹å¦‚下åQ?/p>

  1. æœåŠ¡å™¨åˆ›å»ÞZ¸€ä¸ªè¢«åŠ¨å¥—æŽ¥å­—åQŒå¼€å§‹åó@环侦å¬å®¢æˆïL«¯çš„连接ã€?/li>
  2. 客户端创å»ÞZ¸€ä¸ªä¸»åŠ¨å¥—æŽ¥å­—åQŒè¿žæŽ¥æœåС噍ã€?/li>
  3. æœåŠ¡å™¨æŽ¥å—客æˆïL«¯çš„连接,òq¶åˆ›å»ÞZ¸€ä¸ªä»£è¡¨è¯¥˜qžæŽ¥çš„主动套接字ã€?/li>
  4. æœåŠ¡å™¨å’Œå®¢æˆ·ç«¯é€šè¿‡æ­¥éª¤ 2 å’?3 中创建的两个ä¸ÕdŠ¨å¥—æŽ¥å­—è¿›è¡Œæ•°æ®ä¼ è¾“ã€?/li>

䏋颿˜¯è¿žæŽ¥è¿‡½E‹çš„图解åQ?/p>

TCP ˜qžæŽ¥
TCP ˜qžæŽ¥

一个简å•çš„ TCP æœåŠ¡å™?/h1>

JDK æä¾›äº?ServerSocket ¾cÀL¥ä»£è¡¨ TCP æœåŠ¡å™¨çš„è¢«åŠ¨å¥—æŽ¥å­—ã€‚ä¸‹é¢çš„ä»£ç æ¼”示了一个简å•çš„ TCP æœåŠ¡å™¨ï¼ˆå¤šçº¿½E‹é˜»å¡žæ¨¡å¼ï¼‰åQŒå®ƒä¸æ–­ä¾¦å¬òq¶æŽ¥å—客æˆïL«¯çš„连接,然厞®†å®¢æˆïL«¯å‘é€è¿‡æ¥çš„æ–‡æœ¬æŒ‰è¡Œè¯Õd–åQŒå…¨æ–‡è{æ¢äؓ大写åŽè¿”回给客户端,直到客户端å‘逿–‡æœ¬è¡Œ byeåQ?/p>

public class TcpServer implements Runnable {
    private ServerSocket serverSocket;

    public TcpServer(int port) throws IOException {
        // 创徾l‘定到æŸä¸ªç«¯å£çš„ TCP æœåŠ¡å™¨è¢«åŠ¨å¥—æŽ¥å­—ã€?
        serverSocket = new ServerSocket(port);
    }

    @Override
    public void run() {
        while (true) {
            try {
                // ä»¥é˜»å¡žçš„æ–¹å¼æŽ¥å—一个客æˆïL«¯˜qžæŽ¥åQŒè¿”回代表该˜qžæŽ¥çš„主动套接字ã€?
                Socket socket = serverSocket.accept();
                // 在新¾U¿ç¨‹ä¸­å¤„ç†å®¢æˆïL«¯˜qžæŽ¥ã€?
                new Thread(new ClientHandler(socket)).start();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }
}

public class ClientHandler implements Runnable {
    private Socket socket;

    public ClientHandler(Socket socket) {
        this.socket = Objects.requireNonNull(socket);
    }

    @Override
    public void run() {
        try (Socket s = socket) {  // å‡å°‘代ç é‡çš„花招…â€?
            // 包装套接字的输入‹¹ä»¥è¯Õd–客户端å‘é€çš„æ–‡æœ¬è¡Œã€?
            BufferedReader in = new BufferedReader(new InputStreamReader(
                    s.getInputStream(), StandardCharsets.UTF_8));
            // 包装套接字的输出‹¹ä»¥å‘客æˆïL«¯å‘é€è{æ¢ç»“æžœã€?
            PrintWriter out = new PrintWriter(new OutputStreamWriter(
                    s.getOutputStream(), StandardCharsets.UTF_8), true);

            String line = null;
            while ((line = in.readLine()) != null) {
                if (line.equals("bye")) {
                    break;
                }

                // ž®†è{æ¢ç»“果输出给客户端ã€?
                out.println(line.toUpperCase(Locale.ENGLISH));
            }
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
}
    

é˜Õd¡žæ¨¡å¼çš„ç¼–½E‹æ–¹å¼ç®€å•,但存在性能问题åQŒå› ä¸ºæœåС噍¾U¿ç¨‹ä¼šå¡æ­Õdœ¨æŽ¥å—客户端的 accept() æ–ÒŽ³•上,ä¸èƒ½æœ‰æ•ˆåˆ©ç”¨èµ„æºã€‚套接字支æŒéžé˜»å¡žæ¨¡å¼ï¼ŒçŽ°åœ¨æš‚æ—¶ç•¥è¿‡ã€?/p>

一个简å•çš„ TCP 客户ç«?/h1>

JDK æä¾›äº?Socket ¾cÀL¥ä»£è¡¨ TCP 客户端的ä¸ÕdŠ¨å¥—æŽ¥å­—ã€‚ä¸‹é¢çš„ä»£ç æ¼”示了上˜q°æœåŠ¡å™¨çš„å®¢æˆïL«¯åQ?/p>

public class TcpClient implements Runnable {
    private Socket socket;

    public TcpClient(String host, int port) throws IOException {
        // 创徘qžæŽ¥åˆ°æœåŠ¡å™¨çš„å¥—æŽ¥å­—ã€?
        socket = new Socket(host, port);
    }

    @Override
    public void run() {
        try (Socket s = socket) {  // 冿¬¡å‡å°‘代ç é‡â€¦â€?
            // 包装套接字的输出‹¹ä»¥å‘æœåС噍å‘逿–‡æœ¬è¡Œã€?
            PrintWriter out = new PrintWriter(new OutputStreamWriter(
                    s.getOutputStream(), StandardCharsets.UTF_8), true);
            // 包装套接字的输入‹¹ä»¥è¯Õd–æœåŠ¡å™¨è¿”å›žçš„æ–‡æœ¬è¡Œã€?
            BufferedReader in = new BufferedReader(new InputStreamReader(
                    s.getInputStream(), StandardCharsets.UTF_8));

            Console console = System.console();
            String line = null;
            while ((line = console.readLine()) != null) {
                if (line.equals("bye")) {
                    break;
                }

                // ž®†æ–‡æœ¬è¡Œå‘é€ç»™æœåС噍ã€?
                out.println(line);
                // æ‰“å°æœåŠ¡å™¨è¿”å›žçš„æ–‡æœ¬è¡Œã€?
                console.writer().println(in.readLine());
            }

            // 通知æœåŠ¡å™¨å…³é—­è¿žæŽ¥ã€?
            out.println("bye");
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
}
    

ä»?JDK 文档å¯ä»¥çœ‹åˆ°åQ?code>ServerSocket å’?Socket 在åˆå§‹åŒ–的时候,å¯ä»¥è®‘Ö®šä¸€äº›å‚敎ͼŒ˜q˜æ”¯æŒåšg˜qŸç»‘定。这些东西对性能和行为都有所影å“。下一½‹‡æ–‡ç« å°†è¯¦è§£˜q™ä¸¤ä¸ªç±»çš„åˆå§‹åŒ–ã€?/p>

]]>Java ¾|‘络¾~–程从èœé¸Ÿåˆ°å«å…½ 1åQšIPhttp://www.aygfsteel.com/shinzey/archive/2011/12/30/367593.html蜀山兆孨龘蜀山兆孨龘Fri, 30 Dec 2011 09:39:00 GMThttp://www.aygfsteel.com/shinzey/archive/2011/12/30/367593.htmlhttp://www.aygfsteel.com/shinzey/comments/367593.htmlhttp://www.aygfsteel.com/shinzey/archive/2011/12/30/367593.html#Feedback0http://www.aygfsteel.com/shinzey/comments/commentRss/367593.htmlhttp://www.aygfsteel.com/shinzey/services/trackbacks/367593.html

我竟然到现在æ‰å‘现《Fundamental Networking in Java》这本神作,真有ç‚ÒŽ— åœ°è‡ªå®¹çš„æ„Ÿè§‰ã€‚最˜q‘几òq´åšçš„都是所谓的ä¼ä¸š¾U§å¼€å‘,å…ä¸äº†å’Œ¾|‘络打交é“,但在实际工作中,往往会采用框架将底层¾l†èŠ‚å’Œä¸Šå±‚åº”ç”¨éš”¼›Õd¼€åQŒæ„Ÿè§‰å°±åƒæ˜¯åœ¨ä¸€ä¸?Word 模æ¿è¡¨å•里é¢å¡«å†™å†…容åQŒåšå‡ºæ¥ä¹Ÿæ²¡ä»€ä¹ˆæˆž®±æ„Ÿã€‚虽然没有ä¸ä½¿ç”¨æ¡†æž¶çš„ç†ç”±ï¼Œä½†æˆ‘˜q˜çœŸæ˜¯æœ‰ç‚ÒŽ€€å¿µå½“åˆç›´æŽ¥ç”¨å¥—接字嚾|‘络¾~–程的日å­ï¼Œæ—¢èƒ½æŽŒæŽ§æ›´å¤šä¸œè¥¿åQŒè¿˜å¯ä»¥å­¦åˆ°æ›´å¤šçŸ¥è¯†åQŒäØ“ç ”ç©¶æ¡†æž¶çš„å®žçŽ°åŽŸç†æ‰“基础。闲è¯å®Œæ¯•,转入今天的正题:IPåQˆInternet ProtocolåQŒäº’è”网åè®®åQ‰ã€?/p>

IP 基础知识

说到 IPåQŒå¤§å¤šæ•°äººçš„½W¬ä¸€å应估计都是 IP 地å€ã€‚å…¶å®?IP 是一¿Uå议,IP 地å€åªæ˜¯å议的一部分。《RFC 791 - INTERNET PROTOCOL》说åQšâ€œäº’è”网åè®®æ˜¯äØ“åœ¨åŒ…äº¤æ¢è®¡ç®—机通信¾|‘络的互è”ç³»¾lŸä¸­ä½¿ç”¨è€Œè®¾è®¡çš„。â€IP 包å«ä¸‰æ–¹é¢çš„功能åQ?/p>

  1. 用于查找ä¸ÀLœºçš„寻倾pÈ»Ÿ
  2. 包格å¼çš„定义
  3. 传输和接收包的规�/li>

IP 的相å…?Java ¾c?/h1>

ä»?Java 的角度æ¥çœ‹ä¸Šé¢è¯´åˆ°çš„三个功能åQŒåªæœ‰ç¬¬ä¸€ä¸ªæ˜¯å¼€å‘äh员需è¦å…³å¿ƒçš„。å¦å¤–两个都ä¾èµ–底层¾pÈ»Ÿçš„实玎ͼŒJDK 也没有æä¾›ç›¸å…³çš„¾cÕdŽ»æ“作。下é¢ä¸€ä¸€ä»‹ç» JDK æä¾›çš„用于处ç?IP 地å€çš„ç±»ã€?/p>

InetAddress

此类用æ¥è¡¨ç¤º IP 地å€åQŒå®ƒæœ‰ä¸¤ä¸ªå­¾c»ï¼šInet4Address å’?Inet6AddressåQŒåˆ†åˆ«ç”¨äºŽå¤„ç?IPv4 å’?IPv6 两个版本。在实际应用中,InetAddress ­‘³ä»¥åº”付¾l大多数情况。它æä¾›äº†ä¸€äº›é™æ€æ–¹æ³•æ¥æž„造实例,能根æ®å‚æ•°æ ¼å¼è‡ªåŠ¨è¯†åˆ?IP 版本åQ?/p>

public static InetAddress[] getAllByName(String host) throws UnknownHostException
è§£æžæŒ‡å®šçš„主机地å€åQŒåƈ˜q”回其所有的 IP 地å€åQ›å¦‚果传å…?IP 地å€å­—符ä¸ÔŒ¼Œåˆ™åªä¼šæ ¡éªŒæ ¼å¼ï¼Œ˜q”回的数¾l„也åªåŒ…å«ä¸€ä¸ªä»£è¡¨è¯¥ IP 地å€çš„实例。例如,想看看谷歌有多少马甲的è¯åQ?code>InetAddress.getAllByName("www.google.com") ž®±å¯ä»¥äº†ã€?/dd>
public static InetAddress getByAddress(byte[] addr) throws UnknownHostException
用表½C?IP 地å€çš„字节数¾l„(专业术语¿UîCؓ“原å§?IP 地å€â€ï¼‰æž„造一个实例。IPv4 地å€å¿…é¡»æ˜?4 个字节,IPv6 å¿…é¡» 16 个。ä¸å¸¸ç”¨ã€?/dd>
public static InetAddress getByAddress(String host, byte[] addr) throws UnknownHostException
用主机地å€å’ŒåŽŸå§?IP åœ°å€æž„造一个实例。此æ–ÒŽ³•应该慎用åQŒå› ä¸ºå®ƒä¸ä¼šå¯¹ä¸»æœºå˜q›è¡Œè§£æžã€‚å³ä½¿ä¸»æœºåä¸?IP 地å€å­—符ä¸ÔŒ¼Œä¹Ÿä¸ä¼šæ£€æŸ¥æ˜¯å¦ä¸Žå­—节数组一致ã€?/dd>
public static InetAddress getByName(String host) throws UnknownHostException
ç”¨ä¸»æœºåœ°å€æž„造一个实例,也å¯ä»¥ç›´æŽ¥ä¼ å…?IP 地å€å­—符ä¸ÔŒ¼Œ½{‰åŒäº?getAllByName(host)[0]ã€?/dd>
public static InetAddress getLocalHost() throws UnknownHostException
˜q”回本机在网¾lœä¸­çš„地å€ã€?/dd>
public static InetAddress getLoopbackAddress()
˜q”å›žçŽ¯å›žåœ°å€ 127.0.0.1åQŒä¸æŠ›å‡ºå¼‚常åQŒç­‰åŒäºŽ getByName("localhost")åQˆä¸è¦å’Œ getLocalHost() æžæØœåQ‰ã€‚环回地å€ä½¿ä¸»æœø™ƒ½å¤Ÿè‡ªå·Þp¿žæŽ¥è‡ªå·±ï¼Œå¸¸è¢«ç”¨æ¥å¯¹åœ¨åŒä¸€å°æœºå™¨ä¸Š‹¹‹è¯•¾|‘络应用½E‹åºã€‚在 IPv4 中,环回地å€çš„网ŒDµäØ“ 127.0.0.0/8åQŒé€šå¸¸ç”?127.0.0.1åQ›IPv6 ä¸­åªæœ‰ä¸€ä¸?::1ã€?/dd>

接下æ¥çœ‹çœ?InetAddress 中定义的部分实例æ–ÒŽ³•åQ?/p>

public byte[] getAddress()
˜q”回原始 IP 地å€ã€?/dd>
public String getCanonicalHostName()
˜q”回全é™å®šåŸŸå。这个方法å¯ä»¥ç”¨æ¥æŽ¢æŸ¥å®žé™…çš„ä¸ÀLœºå,例如 InetAddress.getByName("www.google.com").getCanonicalHostName() ˜q”回 we-in-f99.1e100.netã€?/dd>
public String getHostAddress()
˜q”回构造时传入的主机地å€ã€?/dd>
public String getHostName()
˜q”回ä¸ÀLœºå。如果构造时传入的主机地å€ä¸?IP 地å€å­—符ä¸ÔŒ¼Œåˆ™è°ƒç”?getCanonicalHostName()åQŒå¦åˆ™ç›´æŽ¥è¿”回构造时传入的主机地å€ã€?/dd>
public boolean isAnyLocalAddress()
‹‚€æŸ¥æ˜¯å¦äؓ通酽W¦åœ°å€ã€‚通酽W¦åœ°å€ä¸?0.0.0.0åQˆIPv4åQ‰æˆ– ::0åQˆIPv6åQ‰ï¼Œä»£è¡¨æ‰€æœ‰çš„æœ¬åœ° IP 地å€ã€‚例如,å‡è®¾ç”µè„‘有两å—网å¡ï¼Œå„有一个地å€åQŒå¦‚果想让一个程åºåŒæ—¶ç›‘å¬è¿™ä¸¤ä¸ªåœ°å€åQŒå°±éœ€è¦ç”¨é€šé…½W¦åœ°å€ã€?/dd>
public boolean isLinkLocalAddress()
‹‚€æŸ¥æ˜¯å¦äؓ链èµ\本地地å€ã€‚IPv4 é‡Œå®šä¹‰äØ“åœ°å€ŒD?169.254.0.0/16åQŒIpv6 里是ä»?fe80::/64 为剾~€çš„地å€ã€‚在电脑没蔾|‘的时候查看本æœ?IPåQŒå°±èƒ½çœ‹åˆ°è¿™¿U地å€ã€?/dd>
public boolean isLoopbackAddress()
‹‚€æŸ¥æ˜¯å¦äؓ环回地å€ã€?/dd>
public boolean isSiteLocalAddress()
‹‚€æŸ¥æ˜¯å¦äؓ站点本地地å€ã€‚ç«™ç‚ÒŽœ¬åœ°åœ°å€˜q™ä¸ªåè¯å®žé™…上已¾l过时了åQŒçŽ°åœ¨å«å”¯ä¸€æœ¬åœ°åœ°å€ã€‚IPv4 中未定义åQ›IPv6 ä¸­å®šä¹‰äØ“åœ°å€ŒD?fc00::/7。这些地å€ç”¨äºŽ¿U有¾|‘络åQŒä¾‹å¦‚ä¼ä¸šå†…部的局域网ã€?/dd>

此外˜q˜æœ‰ä¸€äº›æœ‰å…›_¤šæ’­åœ°å€çš„æ–¹æ³•,暂时略过ã€?/p>

JDK é»˜è®¤åŒæ—¶æ”¯æŒ IPv4 å’?IPv6ã€‚å¦‚æžœåªæƒ³ä‹É用一¿U,å¯ä»¥æ ÒŽ®æƒ…å†µž®?java.net.preferIPv4Stack æˆ?java.net.preferIPv6Addresses ˜q™ä¸¤ä¸ªç³»¾lŸå±žæ€§ä¹‹ä¸€è®¾äØ“ true。两个属性的默认值都ä¸?false。一般æ¥è¯´ä¸éœ€è¦åŽ»æƒŠåŠ¨å®ƒä»¬ã€?/p>

SocketAddress

该类是一个空壻I¼Œäº‹å®žä¸Šåº”用程åºä‹É用的是它的唯一å­ç±» InetSocketAddressåQŒç›®å‰è¿˜çœ‹ä¸å‡ø™¿™æ ¯‚®¾è®¡æœ‰ä»€ä¹ˆæ„义。该¾cÕdªä¸è¿‡åœ?InetAddress 的基¼‹€ä¸Šå¢žåŠ äº†ä¸€ä¸ªç«¯å£å±žæ€§ã€?/p>

NetworkInterface

该类代表¾|‘络接å£åQŒä¾‹å¦‚一å—网å¡ã€‚一个网¾lœæŽ¥å£å¯ä»¥ç»‘定一äº?IP 地å€ã€‚具有多个网¾lœæŽ¥å£çš„ä¸ÀLœºè¢«ç§°ä¸ºå¤šå®¿ä¸»ä¸ÀLœºã€‚下é¢çš„代ç å¯æ‰“å°å‡ºæ‰€æœ‰æœ¬æœºç½‘¾lœæŽ¥å£çš„ä¿¡æ¯åQ?/p>

for (NetworkInterface ni : Collections.list(NetworkInterface.getNetworkInterfaces())) {
    System.out.println(ni);
    for (InterfaceAddress ia : ni.getInterfaceAddresses()) {
        System.out.println("\t" + ia);
    }
    System.out.println();
}
    

在我的笔记本上è¿è¡Œç»“æžœäØ“åQ?/p>

name:lo (Software Loopback Interface 1)
	/127.0.0.1/8 [/127.255.255.255]
	/0:0:0:0:0:0:0:1/128 [null]
name:net0 (WAN Miniport (SSTP))
name:net1 (WAN Miniport (L2TP))
name:net2 (WAN Miniport (PPTP))
name:ppp0 (WAN Miniport (PPPOE))
name:eth0 (WAN Miniport (IPv6))
name:eth1 (WAN Miniport (Network Monitor))
name:eth2 (WAN Miniport (IP))
name:ppp1 (RAS Async Adapter)
name:net3 (WAN Miniport (IKEv2))
name:net4 (Intel(R) Wireless WiFi Link 4965AGN)
	/fe80:0:0:0:288a:2daf:3549:1811%11/64 [null]
name:eth3 (Broadcom NetXtreme 57xx Gigabit Controller)
	/10.140.1.133/24 [/10.140.1.255]
	/fe80:0:0:0:78c7:e420:1739:f947%12/64 [null]
name:net5 (Teredo Tunneling Pseudo-Interface)
	/fe80:0:0:0:e0:0:0:0%13/64 [null]
name:net6 (Bluetooth Device (RFCOMM Protocol TDI))
name:eth4 (Bluetooth Device (Personal Area Network))
name:eth5 (Cisco AnyConnect VPN Virtual Miniport Adapter for Windows x64)
name:net7 (Microsoft ISATAP Adapter)
	/fe80:0:0:0:0:5efe:a8c:185%17/128 [null]
name:net8 (Microsoft ISATAP Adapter #2)
name:net9 (Intel(R) Wireless WiFi Link 4965AGN-QoS Packet Scheduler-0000)
name:eth6 (Broadcom NetXtreme 57xx Gigabit Controller-TM NDIS Sample LightWeight Filter-0000)
name:eth7 (Broadcom NetXtreme 57xx Gigabit Controller-QoS Packet Scheduler-0000)
name:eth8 (Broadcom NetXtreme 57xx Gigabit Controller-WFP LightWeight Filter-0000)
name:eth9 (WAN Miniport (Network Monitor)-QoS Packet Scheduler-0000)
name:eth10 (WAN Miniport (IP)-QoS Packet Scheduler-0000)
name:eth11 (WAN Miniport (IPv6)-QoS Packet Scheduler-0000)
name:net10 (Intel(R) Wireless WiFi Link 4965AGN-Native WiFi Filter Driver-0000)
name:net11 (Intel(R) Wireless WiFi Link 4965AGN-TM NDIS Sample LightWeight Filter-0000)
name:net12 (Intel(R) Wireless WiFi Link 4965AGN-WFP LightWeight Filter-0000)


]]>
éžä¸»‹¹åƈå‘工具之 Exchangerhttp://www.aygfsteel.com/shinzey/archive/2011/12/27/367313.html蜀山兆孨龘蜀山兆孨龘Tue, 27 Dec 2011 02:50:00 GMThttp://www.aygfsteel.com/shinzey/archive/2011/12/27/367313.htmlhttp://www.aygfsteel.com/shinzey/comments/367313.htmlhttp://www.aygfsteel.com/shinzey/archive/2011/12/27/367313.html#Feedback0http://www.aygfsteel.com/shinzey/comments/commentRss/367313.htmlhttp://www.aygfsteel.com/shinzey/services/trackbacks/367313.html

Exchanger 用æ¥è®©ä¸¤ä¸ªçº¿½E‹äº’ç›¸ç­‰å¾…åÆˆäº¤æ¢è®¡ç®—¾l“果。这个类的用法很½Ž€å•ï¼Œå› äØ“å®ƒå°±å®šä¹‰äº†ä¸¤ä¸ªé‡è½½çš„ exchange æ–ÒŽ³•åQŒå‚数多的那个无éžå¢žåŠ äº†å¯¹è¶…æ—¶çš„æ”¯æŒã€‚当一个线½E‹è°ƒç”?exchange 的时候(以计½Ž—ç»“æžœä½œä¸ºå‚æ•ŽÍ¼‰åQŒå®ƒž®±å¼€å§‹ç­‰å¾…å¦ä¸€ä¸ªçº¿½E‹è°ƒç”?exchangeåQŒç„¶åŽä¸¤ä¸ªçº¿½E‹åˆ†åˆ«æ”¶åˆ°å¯¹æ–¹è°ƒç”?exchange æ—¶ä¼ å…¥çš„å‚æ•°åQŒä»Žè€Œå®Œæˆäº†è®¡ç®—¾l“果的交æ¢ã€?/p>

ä¸ç”¨å¤ªå¤šçš„解释,˜q行下题q™ä¸ªä¾‹å­ž®×ƒ¸€æ¸…二楚:

final Exchanger<String> e = new Exchanger<>();

new Thread() {
    @Override
    public void run() {
        long id = Thread.currentThread().getId();
        String s = "abc";
        System.out.println("¾U¿ç¨‹ [" + id + "] ½Ž—出 " + s);

        try {
            TimeUnit.SECONDS.sleep(new Random().nextInt(5));
            System.out.println("¾U¿ç¨‹ [" + id + "] 收到 " + e.exchange(s));
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }
    }
}.start();

new Thread() {
    @Override
    public void run() {
        long id = Thread.currentThread().getId();
        String s = "xyz";
        System.out.println("¾U¿ç¨‹ [" + id + "] ½Ž—出 " + s);

        try {
            TimeUnit.SECONDS.sleep(new Random().nextInt(5));
            System.out.println("¾U¿ç¨‹ [" + id + "] 收到 " + e.exchange(s));
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }
    }
}.start();
    

˜q行¾l“æžœåQˆå¯èƒ½äØ“åQ‰ï¼š

¾U¿ç¨‹ [9] ½Ž—出 abc
¾U¿ç¨‹ [10] ½Ž—出 xyz
¾U¿ç¨‹ [10] 收到 abc
¾U¿ç¨‹ [9] 收到 xyz

最åŽå¼ºè°ƒä¸‹åQŒè¯¥¾cÕdªé€‚用于两个线½E‹ï¼Œå¦„图用它æ¥å¤„ç†å¤šä¸ªç”Ÿäº§è€…和消费者之间的数æ®äº¤æ¢æ˜¯æ³¨å®šè¦å¤ÞpÓ|的…â€?/p>

]]>
åŸÞZºŽ NIO2 çš?ZIP æ–‡äšg¾pÈ»Ÿhttp://www.aygfsteel.com/shinzey/archive/2011/12/01/365280.html蜀山兆孨龘蜀山兆孨龘Thu, 01 Dec 2011 05:12:00 GMThttp://www.aygfsteel.com/shinzey/archive/2011/12/01/365280.htmlhttp://www.aygfsteel.com/shinzey/comments/365280.htmlhttp://www.aygfsteel.com/shinzey/archive/2011/12/01/365280.html#Feedback1http://www.aygfsteel.com/shinzey/comments/commentRss/365280.htmlhttp://www.aygfsteel.com/shinzey/services/trackbacks/365280.html

以剿ˆ‘曾用两个类åQ?a >ZipItem å’?ZipSystemåQ‰å®žçŽîCº†ä¸€ä¸ªç®€å•çš„ ZIP æ–‡äšg¾pÈ»ŸåQˆä»¥ä¸‹ç®€¿U?ZFSåQ‰ã€‚其实这两个ž®ç±»æŒºå¥½ç”¨çš„åQŒè€Œä¸”支æŒåµŒå¥—çš?ZIP æ–‡äšgåQŒä½†æ˜¯ï¼Œä½†æ˜¯â€¦â€¦JDK 7 丢下æ¥ä¸€æžšå«å?NIO2 的笑气炸弹,引入了一套标准的文äšg¾pÈ»Ÿ APIåQŒæˆ‘承认我中弹了åQŒæ‰‹ç—’了åQŒåˆæ ÒŽ®˜q™å¥— API 釿–°å®žçްäº?ZIP æ–‡äšg¾pÈ»ŸåQŒç»ˆäºŽåœ¨ä»Šå¤©åˆæ­¥å®Œå·¥åQŒå“ˆã€?/p>

è¯è¯´åQŒJDK 7 其实æ†ç»‘销售了一ä¸?ZFSåQŒdemo 目录下还有æºä»£ç ã€‚å¯â€¦â€¦å®ƒè¾¾ä¸åˆ°æˆ‘的奢求,而且 BUG ä¸å°‘。éšä¾‰K€®ä¸¤ä¸ªï¼š

        // com.sun.nio.zipfs.ZipFileSystemProvider ¾cÖM¸­çš„æ–¹æ³?
        @Override
        public Path getPath(URI uri) {

            String spec = uri.getSchemeSpecificPart();
            int sep = spec.indexOf("!/");
            if (sep == -1)
                throw new IllegalArgumentException("URI: "
                    + uri
                    + " does not contain path info ex. jar:file:/c:/foo.zip!/BAR");
            // 难怪该æ–ÒŽ³•始终æŠ?IllegalArgumentException 异常åQŒåŽŸæ¥ä½ ž®å­æŠŠæ–‡ä»¶çš„ URI
            // å½“æˆ ZFS çš?URI 在用…â€?
            return getFileSystem(uri).getPath(spec.substring(sep + 1));
        }

        // com.sun.nio.zipfs.ZipFileSystem ¾cÖM¸­çš„æ–¹æ³?
        @Override
        public PathMatcher getPathMatcher(String syntaxAndInput) {
            int pos = syntaxAndInput.indexOf(':');
            // 丫的åQŒpos == syntaxAndInput.length()åQŸï¼è°å†™çš„?抓出æ¥éž­ž®¸ã€?
            if (pos <= 0 || pos == syntaxAndInput.length()) {
                throw new IllegalArgumentException();
    

很明显,官方 ZFS 没有¾l过代ç å®¡é˜…ã€æ²¡æœ‰ç»˜q‡æµ‹è¯•ã€æ²¡æœ‰ç»˜q‡â€¦â€¦ç„¶åŽï¼Œ@author Xueming ShenåQŒçœŸæ˜¯ä¸¢å’±åŽå¤æ°‘æ—的脸…â€?/p>

下é¢åˆ—个表格详细比较官方 ZFS 和山å¯?ZFSåQ?/p>
比较内容 官方 ZFS 山寨 ZFS
å®žçŽ°æ–¹å¼ å¦è“v炉ç¶åQŒç”¨¾U?Java 釿–°å®žçŽ°äº†å¯¹ ZIP æ–‡äšgæ ¼å¼çš„处ç†ä»£ç ã€?/td> åŸÞZºŽ ZipFile å’?ZipInputStream ˜q™ä¸¤ä¸ªå·²¾l稳定多òq´çš„¾c»ï¼Œä½†æ¶‰åŠäº†å¤§é‡æœ¬åœ°ä»£ç è°ƒç”¨åQŒä¹Ÿè®æ€¼šå½±å“性能ã€?/td>
è¯ÀL“ä½?/td> 支æŒåQŒä¸”通过解压åˆîCÍæ—¶æ–‡ä»¶æ”¯æŒéšæœø™®¿é—®ã€?/td> 支æŒåQŒä½†ä¸æ”¯æŒéšæœø™®¿é—®ã€?/td>
写æ“ä½?/td> 通过解压åˆîCÍæ—¶æ–‡ä»¶è¿›è¡Œæ”¯æŒï¼Œä½†æ— æ³•检‹¹‹åˆ°å…¶ä»–˜q›ç¨‹å¯¹åŒä¸€ä¸?ZIP æ–‡äšg的写æ“作åQŒä¸é€‚ç”¨äºŽåÆˆå‘环境ã€?/td> 䏿”¯æŒã€‚ZIP æ–‡äšg事实上是一个整体,对内部æ¡ç›®çš„ä»ÖM½•修改都å¯èƒ½å¯¼è‡´é‡æž„整个文ä»Óž¼Œå› æ­¤æ‰€è°“的写æ“作必™å»é€šè¿‡ä¸´æ—¶æ–‡äšgæ¥å¤„ç†ï¼Œæ•ˆçŽ‡ä½Žä¸‹åQŒæ„义ä¸å¤§ï¼Œè€Œä¸”难以处ç†åµŒå¥— ZIP æ–‡äšgã€‚è¿™ä¹Ÿç¬¦åˆæˆ‘的原则:ä¸è§£åŽ‹ã€?/td>
嵌套 ZIP æ–‡äšg 䏿”¯æŒã€?/td> 支æŒåQŒå½“然读å–嵌å¥?ZIP æ–‡äšg会慢一些ã€?/td>
åæ–œ¾U¿åˆ†éš”符 䏿”¯æŒï¼Œç›´æŽ¥ç“œæŽ‰ã€?/td> 支æŒåQŒä¸”和标准的斜线分隔½W¦åŒºåˆ«å¯¹å¾…。例如,/abc/ å’?/abc\ ½Ž—ä¸åŒçš„æ–‡äšgåQŒå®žé™…上˜q™ä¸¤ä¸ªèƒ½å¤Ÿåƈ存于 ZIP æ–‡äšg中ã€?/td>
½Iºç›®å½•å 䏿”¯æŒï¼Œç›´æŽ¥ç“œæŽ‰ã€?/td> 支æŒã€‚例å¦?/a/b å’?/a//b 是两个å¯ä»¥åƈ存且ä¸åŒçš„æ–‡ä»¶ã€?/td>

山寨 ZFS 的用法示例:

        Map<String, Object> env = new HashMap<>();
        // ç”¨äºŽè§£ç  ZIP æ¡ç›®åã€‚é»˜è®¤äØ“ Charset.defaultCharset()ã€?
        env.put("charset", StandardCharsets.UTF_8);
        // 指示是å¦è‡ªåŠ¨æŽ¢æµ‹åµŒå¥—çš?ZIP æ–‡äšgã€‚é»˜è®¤äØ“ falseã€?
        env.put("autoDetect", true);
        // 默认目录åQŒç”¨äºŽåˆ›å»ºå’Œè§£æžç›¸å¯¹è·¯å¾„ã€‚é»˜è®¤äØ“â€?â€ã€?
        env.put("defaultDirectory", "/dir/");

        // 从文件创å»ÞZ¸€ä¸?ZFSã€?
        try (FileSystem zfs = FileSystems.newFileSystem(
                URI.create("zip:" + Paths.get("docs.zip").toUri()), env)) {
            Path path = zfs.getPath("app.jar");
            if ((Boolean) Files.getAttribute(path, "isZip")) {
                // 创å¾ä¸€ä¸ªåµŒå¥—çš„ ZFSã€?
                try (FileSystem nestedZfs = zfs.provider().newFileSystem(path, env)) {
                    // 此处çœç•¥è‹¥å¹²è¡Œã€?
                }
            }
        }
    

最åŽåŒæ‰‹å¥‰ä¸Šæºä»£ç åQ?a >è¯ïLŒ›å‡ÀL­¤å¤„ï¼



]]>
é’ÈŸ³˜qç®—½W¦çš„一ä¸?BUGhttp://www.aygfsteel.com/shinzey/archive/2011/11/11/363493.html蜀山兆孨龘蜀山兆孨龘Fri, 11 Nov 2011 03:06:00 GMThttp://www.aygfsteel.com/shinzey/archive/2011/11/11/363493.htmlhttp://www.aygfsteel.com/shinzey/comments/363493.htmlhttp://www.aygfsteel.com/shinzey/archive/2011/11/11/363493.html#Feedback0http://www.aygfsteel.com/shinzey/comments/commentRss/363493.htmlhttp://www.aygfsteel.com/shinzey/services/trackbacks/363493.html

先看出错的代ç ï¼š

        public class Holder<T> {
            private T value;

            public Holder() {
            }

            public Holder(T value) {
                this.value = value;
            }

            public void setValue(T value) {
                this.value = value;
            }

            // 此处çœç•¥è‹¥å¹²è¡Œã€?
        }

        Holder<Object> holder = new Holder<>("xxx");
    

看è“væ¥è¿˜å¥½ï¼Œä½†ç¼–è¯‘çš„æ—¶å€™å´æŠ¥é”™åQ?/p>

Uncompilable source code - incompatible types
  required: zhyi.test.Holder<java.lang.Object>
  found:    zhyi.test.Holder<java.lang.String>

è€è€å®žå®žæŠŠ¾cÕdž‹å†™å‡ºæ¥å°±æ²¡é—®é¢˜ï¼š

        Holder<Object> holder = new Holder<Object>("xxx");
    

如果éžè¦ç”¨é’»çŸŒ™¿½Ž—符的è¯åQŒå¯ä»¥é‡‡å–下列两¿Uæ–¹å¼ä¹‹ä¸€åQ?/p>

        // 使用默认构造器åQŒå†è°ƒç”¨ setValue æ–ÒŽ³•ã€?
        Holder<Object> holder = new Holder<>();
        holder.setValue("xxx");

        // 使用泛型通酽W¦ï¼Œä½†ä¹‹åŽå°±ä¸èƒ½è°ƒç”¨ setValue 了,å¦åˆ™¾~–译出错ã€?
        Holder<? extends Object> holder = new Holder<>("xxx");
    


]]>
éžä¸»‹¹åƈå‘工具之 CyclicBarrierhttp://www.aygfsteel.com/shinzey/archive/2011/10/17/361408.html蜀山兆孨龘蜀山兆孨龘Mon, 17 Oct 2011 03:21:00 GMThttp://www.aygfsteel.com/shinzey/archive/2011/10/17/361408.htmlhttp://www.aygfsteel.com/shinzey/comments/361408.htmlhttp://www.aygfsteel.com/shinzey/archive/2011/10/17/361408.html#Feedback0http://www.aygfsteel.com/shinzey/comments/commentRss/361408.htmlhttp://www.aygfsteel.com/shinzey/services/trackbacks/361408.html

CyclicBarrier 的功能类ä¼égºŽå‰é¢è¯´åˆ°çš?CountDownLatchåQŒç”¨äºŽè®©å¤šä¸ª¾U¿ç¨‹åQˆå­ä»ÕdŠ¡åQ‰äº’相等待,直到共åŒåˆ°è¾¾å…¬å…±å±éšœç‚¹ï¼ˆcommon barrier pointåQ‰ï¼Œåœ¨è¿™ä¸ªç‚¹ä¸Šï¼Œæ‰€æœ‰çš„å­ä“Q务都已完æˆï¼Œä»Žè€Œä¸»ä»ÕdŠ¡å®Œæˆã€?/p>

该类构造的时候除了必™å»è¦æŒ‡å®š¾U¿ç¨‹æ•°é‡åQŒè¿˜å¯ä»¥ä¼ å…¥ä¸€ä¸?Runnable 对象åQŒå®ƒçš?run æ–ÒŽ³•ž®†åœ¨åˆ°è¾¾å…¬å…±å±éšœç‚¹åŽæ‰§è¡Œä¸€‹Æ¡ã€‚å­¾U¿ç¨‹å®Œæˆè®¡ç®—åŽï¼Œåˆ†åˆ«è°ƒç”¨ CyclicBarrier#await æ–ÒŽ³•˜q›å…¥é˜Õd¡žçжæ€ï¼Œç›´åˆ°å…¶ä»–所有孾U¿ç¨‹éƒ½è°ƒç”¨äº† awaitã€?/p>

下é¢ä»ç„¶ä»¥è¿åŠ¨å‘˜å‡†å¤‡èµ›è·‘ä¸ÞZ¾‹æ¥è¯´æ˜?CyclicBarrier 的用法:

            final int count = 8;
            System.out.println("˜q动员开始就ä½ã€?);

            final CyclicBarrier cb = new CyclicBarrier(count, new Runnable() {
                @Override
                public void run() {
                    System.out.println("比赛开�..");
                }
            });

            for (int i = 1; i <= count; i++) {
                final int number = i;
                new Thread() {
                    @Override
                    public void run() {
                        System.out.println(number + " 寂¿åŠ¨å‘˜åˆ°åœºòq¶å¼€å§‹å‡†å¤?..");
                        try {
                            // 准备 2~5 ¿U’é’Ÿã€?
                            TimeUnit.SECONDS.sleep(new Random().nextInt(4) + 2);
                        } catch (InterruptedException ex) {
                        }
                        System.out.println(number + " 寂¿åŠ¨å‘˜ž®×ƒ½ã€?);
                        try {
                            cb.await();
                        } catch (InterruptedException | BrokenBarrierException ex) {
                        }
                    }
                }.start();
            }
            System.out.println("½{‰å¾…所有è¿åŠ¨å‘˜ž®×ƒ½...");
    

˜q行输出åQˆå¯èƒ½ï¼‰ä¸ºï¼š

˜q动员开始就ä½ã€?
1 寂¿åŠ¨å‘˜åˆ°åœºòq¶å¼€å§‹å‡†å¤?..
2 寂¿åŠ¨å‘˜åˆ°åœºòq¶å¼€å§‹å‡†å¤?..
½{‰å¾…所有è¿åŠ¨å‘˜ž®×ƒ½...
3 寂¿åŠ¨å‘˜åˆ°åœºòq¶å¼€å§‹å‡†å¤?..
4 寂¿åŠ¨å‘˜åˆ°åœºòq¶å¼€å§‹å‡†å¤?..
6 寂¿åŠ¨å‘˜åˆ°åœºòq¶å¼€å§‹å‡†å¤?..
8 寂¿åŠ¨å‘˜åˆ°åœºòq¶å¼€å§‹å‡†å¤?..
5 寂¿åŠ¨å‘˜åˆ°åœºòq¶å¼€å§‹å‡†å¤?..
7 寂¿åŠ¨å‘˜åˆ°åœºòq¶å¼€å§‹å‡†å¤?..
1 寂¿åŠ¨å‘˜ž®×ƒ½ã€?
3 寂¿åŠ¨å‘˜ž®×ƒ½ã€?
8 寂¿åŠ¨å‘˜ž®×ƒ½ã€?
6 寂¿åŠ¨å‘˜ž®×ƒ½ã€?
2 寂¿åŠ¨å‘˜ž®×ƒ½ã€?
7 寂¿åŠ¨å‘˜ž®×ƒ½ã€?
5 寂¿åŠ¨å‘˜ž®×ƒ½ã€?
4 寂¿åŠ¨å‘˜ž®×ƒ½ã€?
比赛开�..

最åŽçœ‹çœ?CyclicBarrier å’?CountDownLatch 的主è¦å¼‚åŒï¼š

  1. 两者在构造的时候都必须指定¾U¿ç¨‹æ•°é‡åQŒè€Œä¸”该数é‡åœ¨æž„造åŽä¸å¯ä¿®æ”¹ã€?/li>
  2. å‰è€…å¯ä»¥ä¼ å…¥ä¸€ä¸?Runnable 对象åQŒåœ¨ä»ÕdŠ¡å®ŒæˆåŽè‡ªåŠ¨è°ƒç”¨ï¼Œæ‰§è¡Œè€…äØ“æŸä¸ªå­çº¿½E‹ï¼›åŽè€…å¯åœ?await æ–ÒŽ³•åŽæ‰‹åŠ¨æ‰§è¡Œä¸€ŒDµä»£ç å®žçŽ°ç›¸åŒçš„功能åQŒä½†æ‰§è¡Œè€…䨓ä¸Èº¿½E‹ã€?/li>
  3. å‰è€…在æ¯ä¸ªå­çº¿½E‹ä¸Šéƒ½è¿›è¡Œé˜»å¡žï¼Œç„¶åŽä¸€èµäh”¾è¡Œï¼›åŽè€…仅在主¾U¿ç¨‹ä¸Šé˜»å¡žä¸€‹Æ¡ã€?/li>
  4. å‰è€…å¯ä»¥é‡å¤ä‹É用;åŽè€…的倒计数器归零åŽå°±ä½œåºŸäº†ã€?/li>
  5. 两者的内部实现完全ä¸åŒã€?/li>


      ]]>éžä¸»‹¹åƈå‘工具之 CountDownLatchhttp://www.aygfsteel.com/shinzey/archive/2011/10/14/361277.html蜀山兆孨龘蜀山兆孨龘Fri, 14 Oct 2011 06:22:00 GMThttp://www.aygfsteel.com/shinzey/archive/2011/10/14/361277.htmlhttp://www.aygfsteel.com/shinzey/comments/361277.htmlhttp://www.aygfsteel.com/shinzey/archive/2011/10/14/361277.html#Feedback1http://www.aygfsteel.com/shinzey/comments/commentRss/361277.htmlhttp://www.aygfsteel.com/shinzey/services/trackbacks/361277.html

      ™å‘Öæ€ä¹‰åQ?code>CountDownLatch 是一个用æ¥å€’计数的咚咚。如果柙å¹ä“Q务å¯ä»¥æ‹†åˆ†æˆè‹¥å¹²ä¸ªå­ä»ÕdŠ¡åŒæ—¶˜q›è¡ŒåQŒç„¶åŽç­‰å¾…所有的å­ä“Q务完æˆï¼Œå¯ä»¥è€ƒè™‘使用它ã€?/p>

      该类的用法éžå¸¸ç®€å•。首先构造一ä¸?CountDownLatchåQŒå”¯ä¸€çš„傿•°æ˜¯ä»ÕdŠ¡æ•°é‡åQŒä¸€æ—¦æž„造完毕就ä¸èƒ½ä¿®æ”¹ã€‚接ç€å¯åŠ¨æ‰€æœ‰çš„å­ä“Q务(¾U¿ç¨‹åQ‰ï¼Œä¸”æ¯ä¸ªå­ä»ÕdŠ¡åœ¨å®Œæˆè‡ªå·Þqš„计算åŽï¼Œè°ƒç”¨ CountDownLatch#countDown æ–ÒŽ³•ž®†å€’计数å‡ä¸€ã€‚最åŽåœ¨ä¸Èº¿½E‹ä¸­è°ƒç”¨ CountDownLatch#await æ–ÒŽ³•½{‰å¾…计数器归零ã€?/p>

      例如赛跑的准备阶ŒDµï¼Œå…«å˜q动员先åŽåˆ°è¾¾è“v点åšå¥½å‡†å¤‡ï¼Œç„¶åŽè£åˆ¤æ‰“å“å‘ä×o枪,准备工作ž®Þq»“æŸäº†åQŒæ¯”赛开始。如果把从è¿åŠ¨å‘˜ž®×ƒ½åˆ°å‘令枪å“看åšèµ›è·‘准备ä“Q务,那么æ¯ä¸ª˜q动员的准备˜q‡ç¨‹ž®±æ˜¯å…¶å­ä»ÕdŠ¡åQŒå¯ä»¥ç”¨ CountDownLatch 模拟如下åQ?/p>

              final int count = 8;
              System.out.println("˜q动员开始就ä½ã€?);
      
              // 构�CountDownLatch�
              final CountDownLatch cdl = new CountDownLatch(count);
              for (int i = 1; i <= count; i++) {
                  final int number = i;
                  new Thread() {
                      @Override
                      public void run() {
                          System.out.println(number + " 寂¿åŠ¨å‘˜åˆ°åœºòq¶å¼€å§‹å‡†å¤?..");
                          try {
                              // 让è¿åŠ¨å‘˜éšæœºå‡†å¤‡ 2~5 ¿U’é’Ÿã€?
                              TimeUnit.SECONDS.sleep(new Random().nextInt(4) + 2);
                          } catch (InterruptedException ex) {
                          }
                          System.out.println(number + " 寂¿åŠ¨å‘˜ž®×ƒ½ã€?);
                          // 倒计数å‡ä¸€ã€?
                          cdl.countDown();
                      }
                  }.start();
              }
      
              System.out.println("½{‰å¾…所有è¿åŠ¨å‘˜ž®×ƒ½...");
              try {
                  // ½{‰å¾…倒计数å˜ä¸?0ã€?
                  cdl.await();
                  System.out.println("比赛开始�);
              } catch (InterruptedException ex) {
              }
          

      ˜q行输出åQˆå¯èƒ½ï¼‰ä¸ºï¼š

      ˜q动员开始就ä½ã€?
      1 寂¿åŠ¨å‘˜åˆ°åœºòq¶å¼€å§‹å‡†å¤?..
      2 寂¿åŠ¨å‘˜åˆ°åœºòq¶å¼€å§‹å‡†å¤?..
      4 寂¿åŠ¨å‘˜åˆ°åœºòq¶å¼€å§‹å‡†å¤?..
      ½{‰å¾…所有è¿åŠ¨å‘˜ž®×ƒ½...
      8 寂¿åŠ¨å‘˜åˆ°åœºòq¶å¼€å§‹å‡†å¤?..
      6 寂¿åŠ¨å‘˜åˆ°åœºòq¶å¼€å§‹å‡†å¤?..
      3 寂¿åŠ¨å‘˜åˆ°åœºòq¶å¼€å§‹å‡†å¤?..
      7 寂¿åŠ¨å‘˜åˆ°åœºòq¶å¼€å§‹å‡†å¤?..
      5 寂¿åŠ¨å‘˜åˆ°åœºòq¶å¼€å§‹å‡†å¤?..
      6 寂¿åŠ¨å‘˜ž®×ƒ½ã€?
      1 寂¿åŠ¨å‘˜ž®×ƒ½ã€?
      5 寂¿åŠ¨å‘˜ž®×ƒ½ã€?
      4 寂¿åŠ¨å‘˜ž®×ƒ½ã€?
      7 寂¿åŠ¨å‘˜ž®×ƒ½ã€?
      8 寂¿åŠ¨å‘˜ž®×ƒ½ã€?
      2 寂¿åŠ¨å‘˜ž®×ƒ½ã€?
      3 寂¿åŠ¨å‘˜ž®×ƒ½ã€?
      比赛开始�/pre>
          

      从上é¢çš„例存q˜å¯ä»¥çœ‹å‡?CountDownLatch çš„å±€é™æ€§å’Œ CompletionService ¾cÖM¼¼åQŒåœ¨äºŽæ— æ³•处ç†å­ä»ÕdŠ¡æ•°é‡ä¸ç¡®å®šçš„æƒ…况åQŒä¾‹å¦‚统计æŸä¸ªæ–‡ä»¶å¤¹ä¸­çš„æ–‡äšgæ•°é‡ã€‚å¦å¤–,如果æŸä¸ªå­ä“Q务在调用 countDown 之剞®±æŒ‚掉了åQŒå€’计数就永远ä¸ä¼šå½’零。对于这¿U情况,è¦ä¹ˆç”?finally 之类的手ŒDµä¿è¯?countDown 一定会被调用,è¦ä¹ˆç”¨å¸¦å‚æ•°çš?await æ–ÒŽ³•指定­‘…æ—¶æ—‰™—´ã€?/p>

      ]]>éžä¸»‹¹åƈå‘工具之 CompletionServicehttp://www.aygfsteel.com/shinzey/archive/2011/09/29/359781.html蜀山兆孨龘蜀山兆孨龘Thu, 29 Sep 2011 05:37:00 GMThttp://www.aygfsteel.com/shinzey/archive/2011/09/29/359781.htmlhttp://www.aygfsteel.com/shinzey/comments/359781.htmlhttp://www.aygfsteel.com/shinzey/archive/2011/09/29/359781.html#Feedback0http://www.aygfsteel.com/shinzey/comments/commentRss/359781.htmlhttp://www.aygfsteel.com/shinzey/services/trackbacks/359781.html

      CompletionService 接å£çš„实例å¯ä»¥å……当生产者和消费者的中间处ç†å¼•擎åQŒä»Žè€Œè¾¾åˆ°å°†æäº¤ä»ÕdŠ¡å’Œå¤„ç†ç»“果的代砘q›è¡Œè§£è€¦çš„目的。生产者调ç”?submit æ–ÒŽ³•æäº¤ä»ÕdŠ¡åQŒè€Œæ¶ˆè´¹è€…è°ƒç”?pollåQˆéžé˜Õd¡žåQ‰æˆ– takeåQˆé˜»å¡žï¼‰æ–ÒŽ³•获å–下一个结果:˜q™ä¸€ç‰¹å¾çœ‹è“væ¥å’Œé˜Õd¡žé˜Ÿåˆ—åQ?code>BlockingQueueåQ‰ç±»ä¼û|¼Œä¸¤è€…的区别在于 CompletionService è¦è´Ÿè´£ä“Q务的处ç†åQŒè€Œé˜»å¡žé˜Ÿåˆ—则ä¸ä¼šã€?/p>

      åœ?JDK 中,该接å£åªæœ‰ä¸€ä¸ªå®žçŽ°ç±» ExecutorCompletionServiceåQŒè¯¥¾cÖM‹É用创建时æä¾›çš?Executor 对象åQˆé€šå¸¸æ˜¯çº¿½E‹æ± åQ‰æ¥æ‰§è¡Œä»ÕdŠ¡åQŒç„¶åŽå°†¾l“果攑օ¥ä¸€ä¸ªé˜»å¡žé˜Ÿåˆ—中åQšæžœç„¶æœ¬ž®±æ˜¯ä¸€å®¶äº²å•Šï¼ExecutorCompletionService ž®†çº¿½E‹æ± å’Œé˜»å¡žé˜Ÿåˆ—ç³…åˆåœ¨ä¸€èµøP¼Œä»…仅通过三个æ–ÒŽ³•åQŒå°±å®žçŽ°äº†ä“Q务的异步处ç†åQŒå¯è°“åÆˆå‘ç¼–½E‹åˆå­¦è€…çš„¼œžå…µåˆ©å™¨åQ?/p>

      接下æ¥çœ‹ä¸€ä¸ªä¾‹å­ã€‚楼ä¸ÀLœ‰ä¸€å¤§å † *.java æ–‡äšgåQŒéœ€è¦è®¡½Ž—å®ƒä»¬çš„ä»£ç æ€»è¡Œæ•°ã€‚利ç”?ExecutorCompletionService å¯ä»¥å†™å‡ºå¾ˆç®€å•的多线½E‹å¤„ç†ä»£ç ï¼š

              public int countLines(List<Path> javaFiles) throws Exception {
                  // æ Òޮ处ç†å™¨æ•°é‡åˆ›å»ºçº¿½E‹æ± ã€‚虽然多¾U¿ç¨‹òq¶ä¸ä¿è¯èƒ½å¤Ÿæå‡æ€§èƒ½åQŒä½†é€‚é‡åœ?
                  // å¼€¾U¿ç¨‹ä¸€èˆ¬å¯ä»¥ä»Ž¾pÈ»Ÿéª—å–æ›´å¤šèµ„æºã€?
                  ExecutorService es = Executors.newFixedThreadPool(
                          Runtime.getRuntime().availableProcessors() * 2);
                  // 使用 ExecutorCompletionService 内å¾çš„阻塞队列ã€?
                  CompletionService cs = new ExecutorCompletionService(es);
      
                  // æŒ‰æ–‡ä»¶å‘ CompletionService æäº¤ä»ÕdŠ¡ã€?
                  for (final Path javaFile : javaFiles) {
                      cs.submit(new Callable<Integer>() {
                          @Override
                          public Integer call() throws Exception {
                              // 略去计算å•个文äšg行数的代ç ã€?
                              return countLines(javaFile);
                          }
                      });
                  }
      
                  try {
                      int loc = 0;
                      int size = javaFiles.size();
                      for (int i = 0; i < size; i++) {
                          // take æ–ÒŽ³•½{‰å¾…ä¸‹ä¸€ä¸ªç»“æžœåÆˆ˜q”回 Future 对象。ä¸ç›´æŽ¥˜q”回计算¾l“æžœæ˜¯äØ“äº?
                          // æ•获计算时å¯èƒ½æŠ›å‡ºçš„异常ã€?
                          // poll ä¸ç­‰å¾…,有结果就˜q”回一ä¸?Future 对象åQŒå¦åˆ™è¿”å›?nullã€?
                          loc += cs.take().get();
                      }
                      return loc;
                  } finally {
                      // 关闭¾U¿ç¨‹æ± ã€‚也å¯ä»¥ž®†çº¿½E‹æ± æå‡ä¸ºå­—ŒDµä»¥ä¾‰K‡ç”¨ã€?
                      // 如果ä»ÕdŠ¡¾U¿ç¨‹åQˆCallable#callåQ‰èƒ½å“应中断åQŒç”¨ shutdownNow 更好ã€?
                      es.shutdown();
                  }
              }
          

      最åŽï¼ŒCompletionService ä¹Ÿä¸æ˜¯åˆ°å¤„都能用åQŒå®ƒä¸é€‚åˆå¤„ç†ä»ÕdŠ¡æ•°é‡æœ‰é™ä½†ä¸ªæ•îC¸å¯çŸ¥çš„场景。例如,è¦ç»Ÿè®¡æŸä¸ªæ–‡ä»¶å¤¹ä¸­çš„æ–‡äšg个数åQŒåœ¨éåŽ†å­æ–‡ä»¶å¤¹çš„æ—¶å€™ä¹Ÿä¼šâ€œé€’å½’åœ°â€æäº¤æ–°çš„ä“Q务,但最åŽåˆ°åº•æäº¤äº†å¤šå°‘åQŒä»¥åŠåœ¨ä»€ä¹ˆæ—¶å€™æäº¤å®Œäº†æ‰€æœ‰ä“Q务,都是未知敎ͼŒæ— è®º CompletionService ˜q˜æ˜¯¾U¿ç¨‹æ± éƒ½æ— æ³•˜q›è¡Œåˆ¤æ–­ã€‚è¿™¿U情况åªèƒ½ç›´æŽ¥ç”¨¾U¿ç¨‹æ± æ¥å¤„ç†ã€?/p>

      ]]>
      Ö÷Õ¾Ö©Öë³ØÄ£°å£º Ìì×£| Î÷³ëÏØ| ·áË³ÏØ| º¬É½ÏØ| °¢¿ËËÕÊÐ| º£ÄÏÊ¡| ³¤Ì©ÏØ| ƽÌÁÏØ| Ïã¸ñÀïÀ­ÏØ| ɽÎ÷Ê¡| Óñ»·ÏØ| ³¤×ÓÏØ| Ä˶«ÏØ| ¶¨±ßÏØ| ËÄ»áÊÐ| Ô­ÑôÏØ| Õý¶¨ÏØ| µÂ½­ÏØ| Îå´óÁ¬³ØÊÐ| Á¬Æ½ÏØ| »ëÔ´ÏØ| ºÚË®ÏØ| ÏåÔ«ÏØ| ɳÑóÏØ| ÎÂËÞÏØ| Âí¹ØÏØ| ÐÁ¼¯ÊÐ| ÎèÑôÏØ| ÇåÔ¶ÊÐ| ´óÀíÊÐ| Ä˶«ÏØ| ¹þ¶û±õÊÐ| ·âÇðÏØ| ÷ÖÝÊÐ| ²©ÀÖÊÐ| ººÖÐÊÐ| Î÷³ëÏØ| ²¼ÍÏÏØ| ½­ÓÀÏØ| ѰÎÚÏØ| ÅÌÉ½ÏØ|