Вот оригинальный веб-гусеничный, в котором я написал: (Только для справки)Реализация нитей в Java Web Crawler
https://github.com/domshahbazi/java-webcrawler/tree/master
Это простой веб-обходчик, который посещает заданную начальную веб-страницу, царапанье все ссылки со страницы и добавляет их в очередь (LinkedList), где они затем вылетают один за другим и каждый посетил, где цикл начинается снова. Чтобы ускорить мою программу и для обучения, я попытался реализовать потоки, поэтому я мог бы сразу запустить много потоков, индексируя больше страниц за меньшее время. Ниже каждый класс:
Основной класс
public class controller {
public static void main(String args[]) throws InterruptedException {
DataStruc data = new DataStruc("http://www.imdb.com/title/tt1045772/?ref_=nm_flmg_act_12");
Thread crawl1 = new Crawler(data);
Thread crawl2 = new Crawler(data);
crawl1.start();
crawl2.start();
}
}
Гусеничный класса (Thread)
public class Crawler extends Thread {
/** Instance of Data Structure **/
DataStruc data;
/** Number of page connections allowed before program terminates **/
private final int INDEX_LIMIT = 10;
/** Initial URL to visit **/
public Crawler(DataStruc d) {
data = d;
}
public void run() {
// Counter to keep track of number of indexed URLS
int counter = 0;
// While URL's left to visit
while((data.url_to_visit_size() > 0) && counter<INDEX_LIMIT) {
// Pop next URL to visit from stack
String currentUrl = data.getURL();
try {
// Fetch and parse HTML document
Document doc = Jsoup.connect(currentUrl)
.userAgent("Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.124 Safari/537.36")
.referrer("http://www.google.com")
.timeout(12000)
.followRedirects(true)
.get();
// Increment counter if connection to web page succeeds
counter++;
/** .select returns a list of elements (links in this case) **/
Elements links = doc.select("a[href]"); // Relative URL
// Add newly found links to stack
addLinksToQueue(links);
} catch (IOException e) {
//e.printStackTrace();
System.out.println("Error: "+currentUrl);
}
}
}
public void addLinksToQueue(Elements el) {
// For each element in links
for(Element e : el) {
String theLink = e.attr("abs:href"); // 'abs' prefix ensures absolute url is returned rather then relative url ('www.reddit.com/hello' rather then '/hello')
if(theLink.startsWith("http") && !data.oldLink(theLink)) {
data.addURL(theLink);
data.addVisitedURL(theLink); // Register each unique URL to ensure it isnt stored in 'url_to_visit' again
System.out.println(theLink);
}
}
}
}
DataStruc Класс
public class DataStruc {
/** Queue to store URL's, can be accessed by multiple threads **/
private ConcurrentLinkedQueue<String> url_to_visit = new ConcurrentLinkedQueue<String>();
/** ArrayList of visited URL's **/
private ArrayList<String> visited_url = new ArrayList<String>();
public DataStruc(String initial_url) {
url_to_visit.offer(initial_url);
}
// Method to add seed URL to queue
public void addURL(String url) {
url_to_visit.offer(url);
}
// Get URL at front of queue
public String getURL() {
return url_to_visit.poll();
}
// URL to visit size
public int url_to_visit_size() {
return url_to_visit.size();
}
// Add visited URL
public void addVisitedURL(String url) {
visited_url.add(url);
}
// Checks if link has already been visited
public boolean oldLink(String link) {
for(String s : visited_url) {
if(s.equals(link)) {
return true;
}
}
return false;
}
}
DataStruc - это класс общей структуры данных, к которому будут одновременно обращаться каждый экземпляр потока Crawler.java. DataStruc имеет очередь для хранения ссылок для посещения и администратор для хранения посещенных URL-адресов, чтобы предотвратить ввод цикла. Я использовал ConcurrentLinkedQueue для хранения URL-адресов для посещения, так как я вижу, что он заботится о параллельном доступе. Мне не нужен одновременный доступ с моим arraylist посещаемых URL-адресов, поскольку все, что мне нужно сделать, это добавить к этому и перебрать его, чтобы проверить наличие совпадений.
Моя проблема заключается в том, что когда я сравниваю время работы с использованием одного потока VS, используя 2 потока (по одному и тому же URL), моя однопоточная версия работает быстрее. Я чувствую, что неправильно реализовал потоки, и хотел бы получить некоторые советы, если кто-нибудь сможет определить проблемы?
Спасибо!
Предоставьте текущую реализацию, которую вы используете для многопоточности в виде [SSCCE] (http://sscce.org), иначе мы не сможем вам помочь. Предоставление кода через внешние ссылки неприемлемо на этом сайте. –
Этот вопрос был бы очень странным в это время, но сколько ядер имеет ваш процессор? –
Мой ноутбук двухъядерный –