Java中生产者/消费者与监视器的倍数实例



我正在构建一个从网站下载文件的网络爬虫。我有一个生产者(链接获取者)和一个消费者(下载者)。

两者可以概括如下:

//Fetcher implements Runnable
public void run(){
  while(String link = getLinkFromDatabase != null){
     String htmlContent = HTTPrequest.getHTMLtoString(link);
     ArrayList<String> links = HTTPrequest.getUrlsFromString(htmlContent); //Custom Parser/Extractor
     ArrayList<String> files = HTTPrequest.getFilesFromString(htmlContent);//Custom Parser/Extractor
     String SqlQueryAddLinks = "INSERT IGNORE DUPLICATE INTO [...]"; //Insert query for Links with unique key : sha256 of the url.
     String SqlQUeryAddFiles = "INSERT IGNORE DUPLICATE INTO [...]"; //Insert query for Files with unique key : sha256 of the url.
     Queries.sqlExec(SqlQueryAddLinks);
     int RowAffected = Queries.sqlExec(SqlQueryAddFiles);
     Queries.archiveLink(link);
     Monitor.append(RowAffected);
  }
}
//Downloader implements Runnable
public void run(){
  while(String link = getFileFromeDatabase != null){
     //You don't care of steps here I just download the file
     if(fileDownloaded){
        Queries.archiveFile(link);
        Monitor.take();
     }
  }
}

现在我尝试同步两个线程,以确保链接不会太旧。为此,我使用Monitor(如William Stallings撰写的《操作系统:内部和设计原则》中所述)

public class Monitor{
   int N = 10;
   int count;
   Condition notfull, notempty;
   public Monitor(){
      count = 0;
   }
   public void append(int nbr) throws InterruptedException{
      if(count >= N){
         notfull.wait();
      }
      count+=nbr;
      notempty.signal();
   }
   public void take() throws InterruptedException{
      if(count == 0){
         notempty.wait();
      }
      count--;
      notfull.signal();
   }

现在的问题是,我想通过一个监视器启动多对提取器和下载器同步。我需要创建一个新的监视器对象并将监视器添加到我的Downloader和Fetcher类中吗?或者有更好的方法吗?这本书不是在谈论倍数生产者/消费者,而是在C++中使用函数parbegin(producer, consumer);(我认为它是C++)。

只需仔细观察,由于多种原因,此代码无法编译,并且保证了运行时失败。

a) 您尝试调用静态方法take/append,但它们不是静态的。

b) 您尝试有2个Condition对象,但没有可重入锁。

c) 在等待/通知之前,您甚至没有锁定/解锁条件后面的可重入锁定

d) 您使用Condition.wait()而不是.await().

e) 您正在使用Condition.signal()而不是.signalAll()

最新更新