2017-02-12 19 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