Java ThreadPool用法

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个消费者,问题是如何处理生产者的匮乏.

Enn*_*oji 2

我认为在这种情况下使用等待/通知是合理的。想不出任何直接的方法来使用 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)