2012-02-26 77 views
0

基本上我有一個由ExecutorService和固定線程池使用的小線程類。每個線程實例化我的線程類,並且調用方法被觸發,效果很好!實例化T調用方法中的類可調用類

但是,我真的需要調用另一個類(通過實例化或靜態方式)來處理&返回一些數據在調用方法,但是當試圖這個我可以理解的獲取concurrent.ExecutionException,以及相關的方法。

我認爲這將是更容易貼在這裏我所有的代碼,注意其非常粗糙

MainController

package com.multithreading.excutorservice; 

import java.util.ArrayList; 
import java.util.List; 
import java.util.concurrent.*; 
public class MainController { 


    private static List<String> urls; 

    public static void main(String[] args) { 

     populateList(); 
     // futures to retrieve task results 
     List<Future<ArrayList>> futures = new ArrayList<Future<ArrayList>>(); 
     // results 
     List<ArrayList> results = new ArrayList<ArrayList>(); 
     // pool with 5 threads 
     ExecutorService exec = Executors.newFixedThreadPool(5); 

     // enqueue tasks 
     for(String url: urls) { 
      futures.add(exec.submit(new ThreadTask(url))); 
     } 

     // attempt to move ArrayLists within Future<ArrayList> into a normal ArrayList 
     for(Future<ArrayList> future: futures) { 
      try { 
       results.add(future.get()); 
      } catch (InterruptedException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } catch (ExecutionException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
     } 


    // for(ArrayList<String> s: results) { 
    //  System.out.println(s); 
    // } 
    } 

    private static void populateList() { 
     urls = new ArrayList<String>(); 

     urls.add("http://www.google.com"); 
     urls.add("http://www.msn.co.uk"); 
     urls.add("http://www.yahoo.co.uk"); 
     urls.add("http://www.google.com"); 
     urls.add("http://www.msn.co.uk"); 
     urls.add("http://www.yahoo.co.uk"); 
    } 

} 

ThreadTask

package com.multithreading.excutorservice; 

import java.io.BufferedReader; 
import java.io.InputStreamReader; 
import java.net.URL; 
import java.util.ArrayList; 
import java.util.List; 
import java.util.concurrent.Callable; 



public class ThreadTask implements Callable<ArrayList> { 
     private String url; 
     HtmlParser parseHtml; 

     public ThreadTask(String url) { 
      this.url = url; 
     } 

     public ArrayList call() { 

      int counter = 0; 
      String html = null; 

      try { 
       URL myUrl = new URL(url); 
       BufferedReader reader = new BufferedReader(new InputStreamReader(myUrl.openStream())); 

       while ((html = reader.readLine()) != null) { 
        //counter += inputLine.length(); 
        html += html; 
        } 
       } 
       catch (Exception ex) { 
        System.out.println(ex.toString()); 
       } 

       ArrayList<String> storeLinks = new ArrayList<String>(); 
       HtmlParser par = new HtmlParser(); 
       storeLinks = par.returnNewUrls(html); 

       // for(String s: parseHtml) { 
       // System.out.println(s); 
       // } 

       //returns an ArrayList of URLS which is stored in a List<Future<ArrayList>> temporarily 
       return storeLinks; 

     } 
    } 

的HTMLParser

package com.multithreading.excutorservice; 

import java.util.ArrayList; 
import java.util.concurrent.Callable; 
import java.util.regex.Matcher; 
import java.util.regex.Pattern; 

public class HtmlParser { 

    private final String regex_links = "\\s*(?i)href\\s*=\\s*(\"([^\"]*\")|'[^']*'|([^'\">\\s]+))"; 
    private ArrayList<String> extractedUrls; 

    public ArrayList<String> returnNewUrls (String data) { 

     extractedUrls = new ArrayList<String>(); 

     Pattern p = Pattern.compile(regex_links); 
     Matcher m = p.matcher(data); 
     System.out.println("Test"); 

     while (m.find()) { 
      System.out.println("Test"); 
      extractedUrls.add(m.group(1)); 

     } 

     return getLinks(); 
    } 

    //returns the links 
    public ArrayList getLinks() { 
     return extractedUrls; 
    } 
} 
+0

和異常的完整堆棧跟蹤... – 2012-02-26 11:13:01

回答

1

你在這裏做了一些非常奇怪的事情。多個線程正在訪問相同的靜態extractedUrls字段,並且每次調用returnNewUrls都會創建一個新字段。在您的returnNewUrls方法中,創建一個新的ArrayList,其方法範圍爲,其局部爲。沿着線的東西:

public static ArrayList<String> returnNewUrls(String data) { 
    ArrayList<String> urls = new ArrayList<String>(); 
    addStuffToUrlsList(); 
    return urls; 
} 

另一件事 - 不是一個錯誤,但是你在做不必要的東西 - 在調用方法,你並不需要創建一個新的列表,如果你只是分配給一個變量:

ArrayList<String> parseHtml = new ArrayList<String>(); 
parseHtml = HtmlParser.returnNewUrls(html); 

這是更好的:

ArrayList<String> parseHtml = HtmlParser.returnNewUrls(html); 
+0

哇遺忘我已經試過了靜態,結束留下的代碼不正確的負載,感謝 – Ash 2012-02-26 11:19:32

+0

作爲@rfq指出,靜態字段應該避免,特別是工作時與線程! – claesv 2012-02-26 11:24:32

+0

這個問題最終與解析有關,但是你幫助了,謝謝:) – Ash 2012-02-26 13:51:12

0

你有幾個併發任務,但它們使用相同的變量HtmlParser.extractedUrls?沒有任何同步。在returnNewUrls方法內移動這個變量。 順便說一句,即使沒有併發性,也不鼓勵使用靜態變量,特別是在這種情況下,它可以很容易地用局部變量替換。

相關問題