Ant*_*kov 7 java concurrency multithreading java.util.concurrent
我正在尝试编写一个多线程的Web爬虫.
我的主要入门类有以下代码:
ExecutorService exec = Executors.newFixedThreadPool(numberOfCrawlers);
while(true){
URL url = frontier.get();
if(url == null)
return;
exec.execute(new URLCrawler(this, url));
}
Run Code Online (Sandbox Code Playgroud)
URLCrawler获取指定的URL,解析HTML从中提取链接,并将看不见的链接安排回边界.
边界是未抓取的URL队列.问题是如何编写get()方法.如果队列为空,则应等待任何URLCrawlers完成,然后再次尝试.仅当队列为空且当前没有活动的URLCrawler时,它才应返回null.
我的第一个想法是使用AtomicInteger来计算当前工作URLCrawler的数量以及notifyAll()/ wait()调用的辅助对象.开始时每个爬虫都会增加当前工作URLCrawler的数量,并在退出时递减它,并通知对象它已完成.
但我读到notify()/ notifyAll()和wait()是一些不赞成做线程通信的方法.
我应该在这个工作模式中使用什么?它类似于M生产者和N个消费者,问题是如何处理生产者的匮乏.
我认为在这种情况下使用等待/通知是合理的。想不出任何直接的方法来使用 juc 来做到这一点
在类中,让我们调用 Coordinator:
private final int numOfCrawlers;
private int waiting;
public boolean shouldTryAgain(){
synchronized(this){
waiting++;
if(waiting>=numOfCrawlers){
//Everybody is waiting, terminate
return false;
}else{
wait();//spurious wake up is okay
//waked up for whatever reason. Try again
waiting--;
return true;
}
}
public void hasEnqueued(){
synchronized(this){
notifyAll();
}
}
Run Code Online (Sandbox Code Playgroud)
然后,
ExecutorService exec = Executors.newFixedThreadPool(numberOfCrawlers);
while(true){
URL url = frontier.get();
if(url == null){
if(!coordinator.shouldTryAgain()){
//all threads are waiting. No possibility of new jobs.
return;
}else{
//Possible that there are other jobs. Try again
continue;
}
}
exec.execute(new URLCrawler(this, url));
}//while(true)
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
3504 次 |
最近记录: |