Dobrý deň,
učim sa pracovať v jave s viacerymi vlaknami, a tak som si vymyslel take zadanie, že pomocou knihovne Jsoup zparsujem html stranku a vytiahnem z nej všetky odkazy. Tieto odkazy uložim do fronty. Podla toho či bol už dosiahnuty počet odkazov tak sa odkazy pridavaju. Pre lepšiu efektivitu chcem načitavať stranky vo viacerych vlaknach. Na to použivam Thread Pool.
Ako frontu použivam ArrayBlockingQueue. Problem je v tom, že mi to nefunguje tak ako by malo. ExecutorService sice spustí vlakno ale neprida do fronty žiadne nové odkazy ale pokial vo vnutornej triede CollectThread zavolam v konštruktore metodu run() tak to funguje ale vytvoria sa duplicitne zaznamy( a volat v konštruktore run() je aj tak asi blbosť nie?

) Keď ju tam nevolam tak to funguje tak že tam prida niektore odkazy, inak je tam proste null.
Snažim sa prist na to prečo to má take správanie, napadá ma iba to že je to nejako blbo sychronizovane ale nejako si v tom neviem najst chybu a opraviť ju. Preto by som chcel poprosiť niekoho kto sa rozumie problematike aby sa na to pozrel a poradil mi kde robim chybu a hlavne prečo mi to nefunguje tak ako si to prestavujem:). Ďakujem
Tu je kod:
package collector;
import java.io.IOException;
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 url;
private int links; //predanie parametru konštruktora
private LinksCounter clinks; //count links
private ArrayBlockingQueue<String> LinksList;
public Collector(String baseURL, int Nlinks){
this.url = baseURL;
this.links = Nlinks;
this.clinks = new LinksCounter(0);
this.LinksList = new ArrayBlockingQueue<String>(links);
try {
LinksList.add(url);
CollectFromWeb();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private synchronized void GetLinksList(Document html) throws InterruptedException{
Elements collectedLinks = html.select("a[href]");
for(Element link:collectedLinks){
if(clinks.get() == links) break;
else{
String current = link.attr("abs:href");
if(!current.equals(url) && current.startsWith(url) && !current.contains("#")){
LinksList.put(current);
clinks.up();
}
}
}
}
private void CollectFromWeb() throws InterruptedException{
ExecutorService executor = Executors.newFixedThreadPool(4);
for(int i = 0; i < links; i++){
CollectThread worker = new CollectThread(LinksList.take());
executor.execute(worker);
System.out.println("Collecting from "+LinksList.peek());
}
executor.shutdown();
System.out.println(clinks.get());
}
public void WriteOutQueue(){
while(!LinksList.isEmpty()){
System.out.println(LinksList.poll());
}
System.out.println(clinks.get());
}
public void DuplicityTester(){}
class CollectThread implements Runnable{
private String url;
public CollectThread(String url) {
this.url = url;
}
@Override
public void run() {
//ak je potrebova zbierame linky
if(clinks.get() != links){
try {
Document html = Jsoup.connect(url).get();
GetLinksList(html);
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName());
}
}
class LinksCounter{
private int count;
public LinksCounter(int num){
this.count = num;
}
public synchronized int get(){
return this.count;
}
public synchronized void up(){
this.count++;
}
}
}