지정된 페이지 수에서 링크 수집기를 프로그래밍 중입니다. 더 효율적으로 만들려면 고정 된 크기의 ThreadPool을 사용하고 있습니다. 내가 정말로 멀티 스레딩 영역의 초보자이기 때문에 문제를 해결하는 데 문제가 있습니다. 그래서 내 아이디어는 모든 스레드가 동일한 일을한다는 것입니다 : 페이지에 연결하고 모든 URL을 수집하십시오. 그 후 url은 다음 스레드를 위해 Queue에 추가됩니다.스레드 풀을 사용하여 웹 페이지에서 링크 수집 java
하지만 작동하지 않습니다. 처음에는 baseurl을 분석하고 URL을 추가하십시오. 하지만 처음에는 LinksToVisit.add (baseurl) 만 실행하고 스레드 풀을 사용하여 실행하려고하지만 항상 대기열 및 스레드를 폴링하므로 스레드가 대기열의 맨 위에 새 것을 추가하지 않습니다. null.And 이유는 알 수 없습니다. (
ArrayBlockingQueue하지만 성공하지 못했습니다. 기본 URL 분석으로 해결하는 것은 좋은 해결책이 아닙니다. 왜냐하면 baseurl이 예를 들어 하나의 링크 일 뿐이므로이를 따르지 않기 때문입니다. ... 방법 또는 중요한 뭔가가 HTML 파서으로 내가 사용하고 Jsoup 답변에 대한 감사를
소스 (제거 불필요한 방법) :
package collector;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.Iterator;
import java.util.Map;
import java.util.Scanner;
import java.util.Map.Entry;
import java.util.concurrent.*;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
public class Collector {
private String baseurl;
private int links;
private int cvlinks;
private double time;
private int chcount;
private static final int NTHREADS = Runtime.getRuntime().availableProcessors()*2;
private ConcurrentLinkedQueue<String> LinksToVisit = new ConcurrentLinkedQueue<String>();
private ConcurrentSkipListMap<String, Double> SortedCharMap = new ConcurrentSkipListMap<String, Double>();
private ConcurrentHashMap<String, Double> CharMap = new ConcurrentHashMap<String, Double>();
public Collector(String url, int links) {
this.baseurl = url;
this.links = links;
this.cvlinks = 0;
this.chcount = 0;
try {
Document html = Jsoup.connect(url).get();
if(cvlinks != links){
Elements collectedLinks = html.select("a[href]");
for(Element link:collectedLinks){
if(cvlinks == links) break;
else{
String current = link.attr("abs:href");
if(!current.equals(url) && current.startsWith(baseurl)&& !current.contains("#")){
LinksToVisit.add(current);
cvlinks++;
}
}
}
}
AnalyzeDocument(html, url);
} catch (IOException e) {
e.printStackTrace();
}
CollectFromWeb();
}
private void AnalyzeDocument(Document doc,String url){
String text = doc.body().text().toLowerCase().replaceAll("[^a-z]", "").trim();
chcount += text.length();
String chars[] = text.split("");
CharCount(chars);
}
private void CharCount(String[] chars) {
for(int i = 1; i < chars.length; i++) {
if(!CharMap.containsKey(chars[i]))
CharMap.put(chars[i],1.0);
else
CharMap.put(chars[i], CharMap.get(chars[i]).doubleValue()+1);
}
}
private void CollectFromWeb(){
long startTime = System.nanoTime();
ExecutorService executor = Executors.newFixedThreadPool(NTHREADS);
CollectorThread[] workers = new CollectorThread[this.links];
for (int i = 0; i < this.links; i++) {
if(!LinksToVisit.isEmpty()){
int j = i+1;
System.out.println("Collecting from "+LinksToVisit.peek()+" ["+j+"/"+links+"]");
//Runnable worker = new CollectorThread(LinksToVisit.poll());
workers[i] = new CollectorThread(LinksToVisit.poll());
executor.execute(workers[i]);
}
else break;
}
executor.shutdown();
while (!executor.isTerminated()) {}
SortedCharMap.putAll(CharMap);
this.time =(System.nanoTime() - startTime)*10E-10;
}
class CollectorThread implements Runnable{
private Document html;
private String url;
public CollectorThread(String url){
this.url = url;
try {
this.html = Jsoup.connect(url).get();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
if(cvlinks != links){
Elements collectedLinks = html.select("a[href]");
for(Element link:collectedLinks){
if(cvlinks == links) break;
else{
String current = link.attr("abs:href");
if(!current.equals(url) && current.startsWith(baseurl)&& !current.contains("#")){
LinksToVisit.add(current);
cvlinks++;
}
}
}
}
AnalyzeDocument(html, url);
}
}
}
답변 해 주셔서 감사합니다. 작동하는 것처럼 보이지만 CollectorThread.run() 내부에서 executor.execute (new CollectorThread (current)) 호출을 완전히 이해하는지 모르겠다. 나는 노동자를 만드는 루프를 제거해야합니까? 어떻게 든 재귀 적으로 작동합니까? 감사 – eXPi