【问题标题】:Executors recursive with Jsoup使用 Jsoup 递归执行器
【发布时间】:2015-11-02 03:33:51
【问题描述】:

我想以给定的格式将 ExecutorService 用于从 url 递归读取路径,我很难回忆递归 getRecursive(element.attr("abs:href"), level);

public class NewClass {

    static String levels[] = {"div.col-md-9 li a", "div#sidebar ul li a"};

    private void getRecursive(String href,int level) {

        if (level > levels.length - 1) {
            return;
        }

        Document doc;
        try {
            doc = Jsoup.connect(href).get();
            Elements elements = doc.select(levels[level]);

            level++;
            ExecutorService executor = Executors.newFixedThreadPool(5);
            for (final Element element : elements) {
                executor.execute(new Runnable() {

                    @Override
                    public void run() {
                        if (!element.attr("href").isEmpty()) {
                            String links = "";
                            links += element.attr("abs:href") + "\n";
                            System.out.println(links);
                            getRecursive(element.attr("abs:href"), level);
                        }
                    }
                });
            }
        } catch (IOException e1) {
            e1.printStackTrace();
        }
    }

    public static void main(String[] args) {
        new NewClass().getRecursive("http://www.java2s.com/", 0);
    }
}

【问题讨论】:

    标签: java jsoup executors


    【解决方案1】:

    level 变量必须是 final 才能在 run() 方法中访问它。在任何情况下,如果您没有正确使用ExecutorService,您的程序并不仅限于5 线程,因为您每次调用getRecursive(...) 方法时都会创建一个新的ExecutorService

    要对每个递归使用相同的ExecutorService,您可以执行以下操作:

    public class NewClass { 
    
        static String levels[] = { "div.col-md-9 li a", "div#sidebar ul li a" };    
        static String links = "";   
    
        private void getRecursive(String href, int level, final ExecutorService executor) { 
    
            if (level > levels.length - 1) {    
                return; 
            }   
    
            Document doc;   
            try {   
                doc = Jsoup.connect(href).get();    
                Elements elements = doc.select(levels[level]);  
                final int flevel = ++level; 
                for (final Element element : elements) {    
                    executor.execute(new Runnable() {   
                        @Override   
                        public void run() { 
                            if (!element.attr("href").isEmpty()) {  
                                links += element.attr("abs:href") + "\n";   
                                System.out.println(links);  
                                getRecursive(element.attr("abs:href"), flevel, executor);   
                            }   
                        }   
                    }); 
                }   
            } catch (IOException e1) {  
                e1.printStackTrace();   
            }   
        }   
    
        public static void main(String[] args) {    
            ExecutorService executor = Executors.newFixedThreadPool(5); 
            new NewClass().getRecursive("http://www.java2s.com/", 0, executor); 
        }   
    }
    

    【讨论】:

    • 我想问你如何检查工作是否已经完成。我试图在 main.But 中应用 executor.isTerminated() 失败
    • @MaTâm isTerminated() 仅在您调用 shutdown() 并且所有提交的任务已完成时才返回 true。当您致电shutdown() 时,ExecutorService 不会接受新的任务,但会完成所有提交的任务。
    • @MaTâm 最好使用awaitTermination(long timeout, TimeUnit unit) 方法,该方法会阻塞(停止调用它的线程上的代码执行),直到所有提交的任务完成。这里是你如何使用它awaitTermination(1, TimeUnit.HOURS)
    • 如果levels.length = 1,规则执行器运行良好,但是如果levels.length>1会出现错误:线程“pool-1-thread-138”java.util.concurrent中的异常。拒绝执行异常
    • 我认为递归终止执行器是一个难题,我在stackoverflow上没有看到它存在,所以我想我会做一个更简单的问题,以后都需要它。请继续讨论这个问题和我一起stackoverflow.com/questions/33512762/…
    猜你喜欢
    • 2020-03-26
    • 1970-01-01
    • 2016-09-19
    • 2020-10-24
    • 2019-08-04
    • 2015-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多