为什么jdk说inputStream .available cant block,但是当我在socket程序中使用时,它会阻塞

时间:2016-05-17 02:24:59

标签: java multithreading sockets

遵循我的代码:

if (is != null) {
    while (is.available() == 0) {

    }
    firstDataPackageEnd = System.currentTimeMillis();
    int count = 0;
    String sdf = null;
    int length = 0;
    int acceptLenth = 0;
    Boolean firstRead = false;
    int headEnd = 0;

    while ((count = is.available()) > 0
            || (this.transferKind == TRANSFER_END_SPECIAL_LENGTH ? length < acceptLenth
                    : headEnd < 2)) {
    /*  System.out.println("允许通过的:" + acceptLenth);
        System.out.println("已经有:" + length);
        System.out.println("有结尾标志:" + headEnd);
    */  length = length + count;
        byte[] b = new byte[count];
        is.read(b);
        sdf = new String(b, "utf-8");
        sb.append(sdf);

        if (sdf.indexOf("\r\n\r\n") != -1) {
            headEnd++;
        }

        if (!firstRead) {
            Matcher matcher = CONTENT_LENGTH_PATTERN.matcher(sdf);
            if (matcher.find()) {
                acceptLenth = Integer.parseInt(matcher.group(1));
                firstRead = true;
                this.transferKind = TRANSFER_END_SPECIAL_LENGTH;
            } else {
                Matcher trunkMatcher = TRANSFER_ENCODING_PATTERN
                        .matcher(sdf);
                if (trunkMatcher.find()) {
                    String encode = trunkMatcher.group(1);
                    if ("chunked".equals(encode)) {
                        acceptLenth = Integer.MAX_VALUE;
                        this.transferKind = TRANSFER_END_TRANKED;
                        firstRead = true;
                    }

                }
            }
        }

    }

当我多次运行该线程时,大约2个小时后,我无法得到我期望的结果,所以我有一个java堆栈转储:

"crawling_thread_socketwatchdog_0" #18 daemon prio=5 os_prio=0
tid=0x00007fb97c3da800 nid=0x605 runnable [0x00007fb965513000]   
java.lang.Thread.State: RUNNABLE
        at java.net.PlainSocketImpl.socketAvailable(Native Method)
        at java.net.AbstractPlainSocketImpl.available(AbstractPlainSocketImpl.java:490)
        - locked <0x00000000c55bd3d0> (a java.net.SocksSocketImpl)
        at java.net.SocketInputStream.available(SocketInputStream.java:258)
        at net.health39.socketmonitor.monitor.AbstractHttpMonitor.testSocketConnectServer(AbstractHttpMonitor.java:67)
        at net.health39.socketmonitor.monitor.impl.HttpSocketDirectMonitor.startHttpConnect(HttpSocketDirectMonitor.java:23)
        at net.health39.crawlingprovider.WebWatchdogImplBySocketProvider.crawl(WebWatchdogImplBySocketProvider.java:141)
        at net.health39.crawlingengine.core.HttpProxyCrawlingProviderBase.crawl(HttpProxyCrawlingProviderBase.java:52)
        at net.health39.crawlingengine.core.CrawlingProviderBase.doCrawlingLoop(CrawlingProviderBase.java:189)
        at net.health39.crawlingengine.core.MultiThreadInitializer$CrawlingWorkerThread.run(MultiThreadInitializer.java:40)

我非常惊讶,它阻止,并且它一直在运行,从信息我猜它阻塞在count = is .available();
有人可以帮助我,(提示:我是中国人,我的英语不是很标准,非常抱歉)

1 个答案:

答案 0 :(得分:-1)

  

为什么JDK说InputStream.available()无法阻止

你误解了这一点。它实际上说的是

  

返回对此输入流可以读取(或跳过)的字节数的估计值,而不会被下一次调用此输入流的方法阻塞。

操作词是'可以阅读......没有阻塞'。这是不会阻止的读取。

但无论如何都是如此。

  

阻止

不,不。你是在一个没有头脑的旋转循环中调用它。删除两个available()调用,使用合理的缓冲区大小,然后阅读。