在T Callable Class的call方法中实例化一个类

时间:2012-02-26 11:00:45

标签: java regex multithreading threadpool

基本上我有一个ExecutorService使用的小线程类和一个固定的线程池。每个线程实例化我的线程类,并且调用call方法,效果很好!

但是我真的需要调用另一个类(通过实例化或静态方法)来处理&在call方法中返回一些数据,但是在尝试这个时,我可以理解得到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;
    }
}

2 个答案:

答案 0 :(得分:1)

你在做一些非常奇怪的事情。多个线程正在访问相同的static 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);

答案 1 :(得分:0)

你有几个并发任务,但他们使用相同的变量HtmlParser.extractedUrls?没有任何同步。在returnNewUrls方法中移动此变量。 BTW即使没有并发性,也不鼓励使用静态变量,特别是在类似的情况下,可以很容易地用局部变量替换它。