我已经使用了FixedThreadPool
。会发生什么是每个线程为一个站点打开一个连接。我想要做的是异步。
我认为这会加快执行速度,因为会使用较少的线程来打开与当前性能相同或更多的连接。
以当前的方式,每个线程等待一段时间没有工作等待连接建立。以这种新方式,它将始终有效。
我想知道是否有办法只用一个线程打开与多个站点的连接。
这是因为我正在做一个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.");
}
答案 0 :(得分:3)
获取网页并不是一项特别需要处理器的工作:除非您从非常快速的本地连接中获取大量小页面,否则您几乎将花费所有时间等待网络。
当然,您应该通过基准测试来查看实际值得使用多少个线程 - 您可能希望有一组固定的线程在共享的生产者/消费者队列中运行。 (您不希望为每个请求创建一个真正的新线程。)
现在应该可能只使用极少数线程,如果你可以异步执行提取(可能是NIO),但我会亲自检查“单独线程”方法是否实际上首先最大化你的CPU。它可能会使代码很多比使用异步更简单,如果瓶颈确实是网络,那么你最终将获得难以维护的代码,以获得很少(如果有的话)的好处。
答案 1 :(得分:1)
查看并查看您是否喜欢Java 7的AsynchronousSocketChannel
。基本上,您发出一个读取请求,当字节可用时,它将调用您的回调。当然,必须在某个线程上调用回调;您可以选择配置线程策略。
答案 2 :(得分:0)
我已将xlightweb用于类似目的,即异步HTTP 。