2012-02-26 98 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方法内移动这个变量。 顺便说一句,即使没有并发性,也不鼓励使用静态变量,特别是在这种情况下,它可以很容易地用局部变量替换。