首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从不同的远程源读取:如何优化线程?

问从不同的远程源读取:如何优化线程?
EN

Stack Overflow用户
提问于 2014-05-25 15:05:04
回答 1查看 60关注 0票数 0

我需要在网上阅读大量的网页。这是我实际上用来获取远程网页的方法。请注意,当前代码是100%工作。

代码语言:javascript
复制
    static private GetWebPageResult getWebPage(PageNode pagenode)
{
    String result;
    String inputLine;
    URI url;
    int cicliLettura=0;
    long startTime=0, endTime, openConnTime=0,connTime=0, readTime=0;
    try
    {
        startTime=System.nanoTime();
        result="";
        url=pagenode.getUri();      //fare qualcosa se getURI è null
        if(Core.logGetWebPage())
            openConnTime=System.nanoTime();
        if(url!=null)
        {
            HttpURLConnection yc = (HttpURLConnection) url.toURL().openConnection(); //controllare yc
            if(url.toURL().getProtocol().equalsIgnoreCase("https"))
                yc=(HttpsURLConnection)yc;
            yc.addRequestProperty("User-Agent", "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-GB;     rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13 (.NET CLR 3.5.30729)"); 
            yc.connect();           //controllare il risultato di .connect => non c'è! al max lancia IOEXC
            if(checkResponseCode(yc.getResponseCode())==false)
                return new GetWebPageResult(GetWebPageResult.ERR_BAD_RESPONSE_CODE,yc.getResponseCode());
            if(Core.logGetWebPage())
                connTime=System.nanoTime();

            BufferedReader in = new BufferedReader(new InputStreamReader(yc.getInputStream()));//può lanciare IOEXC
            /*
            while ((inputLine = in.readLine()) != null)
            {
                result=result+inputLine+"\n";
                cicliLettura++;
            }*/
            StringBuffer buffer = new StringBuffer();
            while ((inputLine = in.readLine()) != null)
            {
                buffer.append(inputLine).append('\n');
                cicliLettura++;
            }
            result = buffer.toString();

            if(Core.logGetWebPage())
                readTime=System.nanoTime();
            in.close();
            yc.disconnect();
            if(Core.logGetWebPage())
            {
                endTime=System.nanoTime();
                        //url.toURL() non è null, controllato prima
                System.out.println(/*result+*/"getWebPage eseguito in "+(endTime-startTime)/1000000+" ms. Size: "+result.length()+" Response Code="+yc.getResponseCode()+" Protocollo="+url.toURL().getProtocol()+" openConnTime: "+(openConnTime-startTime)/1000000+" connTime:"+(connTime-openConnTime)/1000000+" readTime:"+(readTime-connTime)/1000000+" cicliLettura="+cicliLettura+" pagina:"+url.toURL());
            }
            return new GetWebPageResult(result);
        }
        else
            return new GetWebPageResult(GetWebPageResult.ERR_NULL_URI,-2);
    }catch(IOException e){
        System.out.println("Eccezione1: "+e.toString());
        e.printStackTrace();  
        return new GetWebPageResult(GetWebPageResult.ERR_HTML_IOEXCEPTION,-2);
    }catch(ClassCastException e){
        System.out.println("Eccezione2: "+e.toString());
        e.printStackTrace(); 
        return new GetWebPageResult(GetWebPageResult.ERR_CLASS_CAST_EXC,-2);
    }catch(Exception e){
        System.out.println("Eccezione ERR_NOT_LISTED_EXC: "+e.toString());
        return new GetWebPageResult(GetWebPageResult.ERR_NOT_LISTED_EXC,-2);
    }
}

考虑到url不是空的,让我们仔细看看代码

代码语言:javascript
复制
HttpURLConnection yc = (HttpURLConnection) url.toURL().openConnection(); //controllare yc
            if(url.toURL().getProtocol().equalsIgnoreCase("https"))
                yc=(HttpsURLConnection)yc;
            yc.addRequestProperty("User-Agent", "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-GB;     rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13 (.NET CLR 3.5.30729)"); 
            yc.connect();           //controllare il risultato di .connect => non c'è! al max lancia IOEXC
            if(checkResponseCode(yc.getResponseCode())==false)
                return new GetWebPageResult(GetWebPageResult.ERR_BAD_RESPONSE_CODE,yc.getResponseCode());

.openConnection和.connect方法有什么区别?无论如何,当我们打开一个连接时,我们就开始读取数据。

代码语言:javascript
复制
                BufferedReader in = new BufferedReader(new InputStreamReader(yc.getInputStream()));//può lanciare IOEXC
            StringBuffer buffer = new StringBuffer();
            while ((inputLine = in.readLine()) != null)
            {
                buffer.append(inputLine).append('\n');
                cicliLettura++;
            }
            result = buffer.toString();

现在我有了一个BufferedReader来读取数据。问题是,我的带宽通常比远程机器的带宽要大得多,所以我希望能够“同时”从不同的来源读取信息。一种很好的方法似乎可以启动许多线程,并像下面这样修改代码的最后一部分

虽然没有结束文件,那么是否有完整的行可读取?如果是的话,问一个新的行,否则睡一会儿。在这一点上,我继续下一个阅读线程,并做出同样的事情。这是正确的吗?如何实现这一点?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-05-25 17:14:37

这看起来像是一个典型的生产者/消费者场景。您可以通过创建以下类来优化应用程序。如果您还不知道BlockingQueue的概念和生产者-消费者问题,我建议您在继续我的回答/设计之前阅读这。

  1. WebPageResult :表示网页内容的Pojo。包含一个StringBuffer,用于保存网页的结果和网页的名称/url,以标识内容的用途。
  2. ProcessingQueue :一个具有ArrayBlockingQueue的单例类,它包含PageNode对象和方法,可以从这个队列中添加和轮询PageNode
  3. ResultQueue :一个具有ArrayBlockingQueue的单例类,它包含WebPageResult对象和方法,可以从这个队列中添加和轮询WebPageResult。
  4. WebPageReader :实现Runnable,在它的run方法(True)循环中从ProcessingQueue调用轮询方法,并读取队列中轮询的PageNode的内容。从PageNode读取的内容应该包装到WebPageResult中,然后通过调用ResultQueue中的add方法将内容放入ResultQueue中。
  5. WebPageProcessor :实现Runnable,在它的run方法(True)循环中从ResultQueue调用轮询方法,然后对这个内容做你想做的任何事情。

现在所需要做的就是将PageNode对象添加到ProcessingQueue中,启动WebPageReader和WebPageProcessor线程,并观察奇迹的发生。如果你需要澄清的话请告诉我。根据您的需求,您可以选择只启动一个WebPageReader线程和WebPageProcessor线程或多个线程。该设计支持两者。另外,您还可以引入一个线程,通过爬行Web或轮询某种数据库来将PageNode对象添加到ProcessingQueue中,以查找要爬行的页面。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23856666

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档