只使用一个线程就可以打开多个站点的多个连接?

时间:2011-09-29 19:24:29

标签: java http connection web-crawler

更新

我已经使用了FixedThreadPool。会发生什么是每个线程为一个站点打开一个连接。我想要做的是异步。

  1. 向服务器发送请求
  2. 转到下一个请求,无需等待第一个请求完成
  3. 建立请求时,请执行一些操作,通知另一个线程已建立连接并准备下载。
  4. 我认为这会加快执行速度,因为会使用较少的线程来打开与当前性能相同或更多的连接。

    以当前的方式,每个线程等待一段时间没有工作等待连接建立。以这种新方式,它将始终有效。


    问题

    我想知道是否有办法只用一个线程打开与多个站点的连接。

    这是因为我正在做一个webcrawler,我已经做了一个线程来打开一个连接,但是在一定数量的线程之后,这无济于事,因为处理器共享会增加很多。

    我希望这能加快下载的页数。这可能吗?怎么样?

    此代码打开一个连接并进行一些处理。它由打开连接的线程执行

    /*
     * Open connection to a server
     */
    boolean openConnection(Link link) throws Exception {
        //set the connection paramenters
        HttpURLConnection conn = (HttpURLConnection) new URL(link.getOriginalURL().getURL()).openConnection();
        conn.setRequestProperty("User-Agent", ROBOT_NAME);
        conn.setInstanceFollowRedirects(true);
        conn.setConnectTimeout(READ_TIMEOUT);
        conn.setReadTimeout(READ_TIMEOUT);
        link.setConnection(conn);
        //open the connection
        conn.connect();        
        //check the server answer
        if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) {
            return false;
        }
        //analyse the URL of the redirected URL
        urlAnalyzer.fillURL(link.getRedirectedURL(), getRedirectedURL(link.getConnection()));
        return true;
    }
    

    执行连接开启者,每个人都在一个线程中

    /*
     * Start the execution of the connection openers     
     */
    private void executeConnectionOpeners() {
        LOGGER.info("Starting connection openners.");
        /* Execution */
        NameThreadFactory ntf = new NameThreadFactory("Connection Opener");
        crawlerOpenerExecutor = Executors.newFixedThreadPool(nOpeners, ntf);
        for (int i = 0; i < nOpeners; i++) {
            crawlerOpenerExecutor.submit(new ConnectionOpener(this));
        }
        /* End of execution */
        LOGGER.info(nOpeners + " connection openers created and running.");
    }
    

3 个答案:

答案 0 :(得分:3)

获取网页并不是一项特别需要处理器的工作:除非您从非常快速的本地连接中获取大量小页面,否则您几乎将花费所有时间等待网络。

当然,您应该通过基准测试来查看实际值得使用多少个线程 - 您可能希望有一组固定的线程在共享的生产者/消费者队列中运行。 (您不希望为每个请求创建一个真正的新线程。)

现在应该可能只使用极少数线程,如果你可以异步执行提取(可能是NIO),但我会亲自检查“单独线程”方法是否实际上首先最大化你的CPU。它可能会使代码很多比使用异步更简单,如果瓶颈确实是网络,那么你最终将获得难以维护的代码,以获得很少(如果有的话)的好处。

答案 1 :(得分:1)

查看并查看您是否喜欢Java 7的AsynchronousSocketChannel。基本上,您发出一个读取请求,当字节可用时,它将调用您的回调。当然,必须在某个线程上调用回调;您可以选择配置线程策略。

答案 2 :(得分:0)

我已将xlightweb用于类似目的,即异步HTTP