2017-02-12 45 views
0

我試圖構建一個程序,試圖解密使用AES加密爲學校項目加密的文件。我有一個約100,000個英語單詞的列表,並且希望在程序中實現多線程以優化文件中每個單詞嘗試解密所花費的時間。Java - 根據請求關閉併發線程

我有試圖阻止字典的休息時被搜查解密成功完成事件的一個問題 - 「試圖關閉」被打印到控制檯,但現在看來,該線程將繼續通過工作執行程序停止分配新線程之前的其餘字典。

private void startThreads(){ 
    ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); 
    System.out.println("Maximum threads inside pool " + executor.getMaximumPoolSize()); 
    for (int i = 0; i < dict.size(); i++) { 
     String word = dict.get(i); 
     Grafter grafter = new Grafter("Grafter " + i,word); 
     grafter.registerWorkerListener(thread -> { 
      List results = thread.getResults(); 
      for (Iterator iter = results.iterator(); iter.hasNext();) { 
       found = (boolean) iter.next(); 
       if(found){ 
        System.out.println("THE WORD HAS BEEN FOUND!! Attempting shutdown"); 
        executor.shutdown(); 
       } 
      } 
     }); 

     // Start the worker thread 
     Thread thread = new Thread(grafter); 
     thread.start(); 

    } 
    if(!executor.isShutdown()) { 
     executor.shutdown(); 
    } 
} 

和「受賄」運行的類的實現如下:

在我的主要程序,線程使用此方法運行

public class Grafter implements Runnable{ 

private String NAME; 
private final String WORD; 
private List listeners = new ArrayList(); 
private List results; 

public Grafter(String name, String word){ 
    NAME = name; 
    WORD = word; 
} 

public String getName(){ 
    return NAME; 
} 

@Override 
public void run() { 
    if (tryToDecrypt(WORD) == true){ 
     System.out.println("Thread: '" + NAME + "' successfully decrypted using word: \"" + WORD + "\"."); 
     results = new ArrayList(); 
     results.add(true); 

     // Work done, notify listeners 
     notifyListeners(); 
    }else{ 
     results = new ArrayList(); 
     results.add(false); 

     // Work done, notify listeners 
     notifyListeners(); 
    } 
} 

private void notifyListeners() { 
    for (Iterator iter = listeners.iterator(); iter.hasNext();) { 
     GrafterListener listener = (GrafterListener) iter.next(); 
     listener.workDone(this); 
    } 
} 

public void registerWorkerListener(GrafterListener listener) { 
    listeners.add(listener); 
} 

public List getResults() { 
    return results; 
} 

private boolean tryToDecrypt(String word){ 
    //Decryption performed, returning true if successfully decrypted, 
    //Returns false if not 
} 

} 

正確的字是正確的在字典的頂部,所以在程序執行的早期發現成功。但是,在程序結束之前會有很長的停頓(正如字典的其餘部分所做的那樣)。

我正在尋找有關executor.shutdown()的定位的幫助,以及如何在解密成功完成後停止解析字典的其餘部分。

+0

我在發佈之前檢查了以前的帖子,但是在使用executor.shutdownNow()的建議後,我仍然遇到同樣的問題。 executor.awaitTermination();'在該線程 – user3379139

+2

閱讀有關處理中斷的部分。 – shmosel

+0

[Shmosel](https://stackoverflow.com/users/1553851/shmosel)是完全正確的。您需要[妥善處理中斷(https://docs.oracle.com/javase/tutorial/essential/concurrency/interrupt.html),並調用'shutdownNow'。 –

回答

1

您的主要問題是您實際上並未將您的runnables提交給執行程序。因此,對執行程序調用關閉對所有已生成的線程都沒有影響。

不是創建一個新的線程,而不是這樣做的:

executor.submit(grafter) 

這應該讓你最的方式,但是如果你想要將服務迅速關閉,乾淨有更多一點,你可以做。 shmosel在評論中提供的鏈接應該可以幫助你。

順便說一句,你這樣做的方式不會很有效率,我不認爲。基本上,你正在爲你的字典中的每個單詞創建一個新任務,這意味着你有大量的任務(在你的情況下爲100K)。這意味着管理和調度所有這些任務的開銷很可能是您程序執行工作的重要部分。相反,你可能會想打破單詞列表成一定數量的子列表中的每個包含單詞的數量相等,然後讓你運行的進程只子列表。

+0

哈,甚至沒有注意到。好地方! –

+0

您的最後一段不完全正確,因爲OP正在使用'FixedThreadPool' - 這意味着應該有正確的線程數。你的理由是,用大量任務發送垃圾郵件並不理想,但不應該因爲沒有線程過量使用而發生顛簸。 –

+0

當然 - 如果他使用了一些無限的線程池,情況會更糟糕 - 但事實是,他們將不得不排隊大量任務,然後線程池將不得不將所有隊列出隊這些任務給執行者。我猜這是否重要取決於在tryToDecrypt中完成了多少工作,但如果每個單詞的任務是實現此目標的最有效方式,我會感到非常驚訝, – d80tb7