【问题标题】:It's possible open multiple connections to multiple sites using only one thread?是否可以仅使用一个线程打开到多个站点的多个连接?
【发布时间】:2011-09-29 19:24:29
【问题描述】:

更新

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

  1. 向服务器发送请求
  2. 无需等待第一个请求完成即可转到下一个请求
  3. 当请求建立后,通知另一个线程连接已建立并准备好下载。

我认为这将加快执行速度,因为将使用更少的线程来打开与当前性能相同或更多的连接。

在当前的方式中,每个线程都会等待一段时间,而无需等待连接建立。以这种新方式,它将始终有效。


问题

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

这是因为我在做一个网络爬虫,我已经做了一个线程来打开一个连接,但是在一定数量的线程之后,这并没有帮助,因为处理器共享会增加很多。

我希望这可以加快下载页面的数量。有可能这样做吗?怎么样?

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

/*
 * 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.");
}

【问题讨论】:

  • 为什么不使用固定大小的线程池?
  • 分享你的爬虫Thread代码块,社区可以提供更好的反馈

标签: java http connection web-crawler


【解决方案1】:

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

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

现在应该可能只使用很少的线程,如果您可以异步执行提取(可能使用 NIO),但我会亲自检查“分离线程”方法是否是 实际上首先最大化你的CPU。它可能会使代码比使用异步更简单,如果瓶颈真的是网络,那么你最终会得到难以维护的代码,而几乎没有(如果有的话)收益。

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        猜你喜欢
        • 2021-10-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-02-11
        • 1970-01-01
        • 2019-08-14
        相关资源
        最近更新 更多