簡體   English   中英

Java中的執行者終止遞歸如何?

[英]How is an executor termination recursion in java?

這是一個程序,它使用遞歸和執行程序來讀取以前格式的信息站點。它工作正常,我的問題是測試程序是否完成和成功通知。

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();   
        }   
    }   

如果levels.length = 1 ,則規則執行器運行良好,但是如果levels.length> 1將出現錯誤:線程“ pool-1-thread-138”中的異常java.util.concurrent.RejectedExecutionException

    public static void main(String[] args) {    
    try {
        ExecutorService executor = Executors.newFixedThreadPool(5);
        new NewClass().getRecursive("http://www.java2s.com/", 0, executor);
        executor.shutdown();
        executor.awaitTermination(1, TimeUnit.HOURS);
        if (executor.isTerminated()) {
            JOptionPane.showMessageDialog(null, "Success");
        }
    } catch (Exception ex) {
        Logger.getLogger(NewClass.class.getName()).log(Level.SEVERE, null, ex);
    }
}   
}

問題是,你打電話executor.execute調用后executor.shutdown() awaitTermination方法僅等待調用shutdown之前提交的任務。

這是發生這種情況的原因:

  • 假設程序在線程main上啟動。
  • executor.execute的第一次調用在main
  • 假設執行程序現在在thread-pool-1上運行,它也調用executor.execute
  • 但是在執行這些新任務之前,我們跳回main並調用executor.shutdown
  • 執行程序可能會再次開始執行任務,也許這次是在thread-pool-2 ,它會嘗試調用executor.execute 但是,已經調用了executor.shutdown() ,因此引發了java.util.concurrent.RejectedExecutionException

有幾種解決方法:

  1. 在這種情況下,使用執行程序可能會過分殺傷。 僅執行單線程操作就足夠了。
  2. 可以重構代碼,以便最后一個executor.execute可以調用executor.shutdown 但是,如果沒有明顯的最后通話,則將不可能。
  3. 如果絕對需要在主線程上執行此操作,則可以在其自己的線程中執行整個遞歸調用:

     public static void main(String[] args) { try { ExecutorService executor = Executors.newSingleThreadExecutor(); executor.execute(new Runnable() { @Override public void run() { NewClass.getRecursive("http://www.java2s.com/", 0); } }); executor.shutdown(); executor.awaitTermination(1, TimeUnit.HOURS); if (executor.isTerminated()) { JOptionPane.showMessageDialog(null, "Success"); } } catch (Exception ex) { Logger.getLogger(NewClass.class.getName()).log(Level.SEVERE, null, ex); } } 

     private static class NewClass { static String levels[] = { "div.col-md-9 li a", "div#sidebar ul li a" }; static String links = ""; private static 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]); final int flevel = ++level; for (final Element element : elements) { if (!element.attr("href").isEmpty()) { links += element.attr("abs:href") + "\\n"; System.out.println(links); getRecursive(element.attr("abs:href"), flevel); } } } catch (IOException e1) { e1.printStackTrace(); } } } 

關閉ExecutorService后,您無法提交任何新任務,處理完所有級別后,遞歸似乎停止了(此后您不提交任何新任務),您可以執行以下操作:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM