几种http请求的实现方式

需要在程序中访问一批url,类似爬虫的东西,想了几种方案:

1. 同步执行
for循环一条条抓取,这种方式最简单但效率最差,遇到网站响应慢的url会阻塞掉后面的执行。


2.异步方式
每个url开一个进程来处理:


String[] urls = { "url1", "url2", "url3", "url4", "url5", "url6",
"url7" };
for (String url : urls) {

Thread t = new Thread(new Runnable(){

public void run(){
//fetch site
}

})
}
t.start()


这种方式能利用多线程同时并发http请求,最大的提高吞吐量。但这种方案也有问题:
1. 多少个图片就开多少个线程,线程数不可控,如果是一万张图片就启动一万个thread,明显资源有问题。
2. 大量启动线程也有性能消耗。

3. 使用线程池
通过配置线程池来做到资源可控。

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

public class ThreadPool {

private List<Thread> threads = new ArrayList<Thread>();

private BlockingQueue<Runnable> queue = new ArrayBlockingQueue<Runnable>(20);

public ThreadPool(int size) {
for (int i = 0; i < size; ++i) {
Thread thread = new Thread(new Worker(queue));
// thread.setDaemon(true);
thread.start();
threads.add(thread);
}
}

public void sumbit(Runnable runnable) {
queue.add(runnable);
}


private static class Worker implements Runnable {

private BlockingQueue<Runnable> queue;

public Worker(BlockingQueue<Runnable> queue) {
super();
this.queue = queue;
}

@Override
public void run() {
while (true) {

Runnable runnable = queue.poll();
if(runnable!=null){
runnable.run();
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

}
}


public class ThreadPoolFetcher {

public static void main(String[] args) {
ThreadPool pool = new ThreadPool(7);
String[] urls = { "url1", "url2", "url3", "url4", "url5", "url6",
"url7" };

for (String url : urls) {
pool.sumbit(new Fetcher(url));
}


}

private static class Fetcher implements Runnable {
private String url;

public Fetcher(String url) {
super();
this.url = url;
}

public void run() {

System.out.println(Thread.currentThread().getName() + ":" + url);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

这种方式利用生产者消费者的方式来实现线程池,做到资源可控。
不过这种方式有点问题是,执行完成之后线程池里的线程不会退出。

4. 使用Executors轻松搞定:
最后还是使用jdk5提供的Executors轻松搞定吧:

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


public class Fetcher {

public static void main(String[] args) throws InterruptedException {

String[] urls = {"url1","url2","url3","url4","url5","url6","url7"};
ExecutorService exs = Executors.newFixedThreadPool(100);
List<Callable<String>> tasks = new ArrayList<Callable<String>>();
for(String url :urls){
tasks.add(new FetchImageTask(url));
}
exs.invokeAll(tasks);
System.out.println("end");
exs.shutdown();
}


/**
* @author yunpeng
*
*/
private static class FetchImageTask implements Callable<String>{

private String url;

public FetchImageTask(String url) {
super();
this.url = url;
}
@Override
public String call() throws Exception {
System.out.println(Thread.currentThread().getName());
Thread.sleep(3000);
return "ok"+url;
}
}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值