Java - 根据请求关闭并发线程

时间:2017-02-12 09:50:20

标签: java multithreading threadpoolexecutor

我正在尝试构建一个程序,尝试解密使用AES加密为学校项目加密的文件。我有一个大约100,000个英文单词的列表,并希望在程序中实现多线程,以优化文件中每个单词尝试解密所花费的时间。

在解密成功完成时尝试停止搜索的其余字典时出现问题 - “正在尝试关闭”正在打印到控制台,但似乎线程继续在其余部分工作执行程序停止分配新线程之前的字典。

在我的主程序中,线程使用以下方法运行:

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

'grafter'runnable类的实现如下:

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()定位的帮助,以及如何在解密成功完成后停止解析字典的其余部分。

1 个答案:

答案 0 :(得分:1)

您的主要问题是您实际上没有将您的可运行程序提交给执行程序。因此,在执行程序上调用shutdown对您生成的所有线程都没有影响。

而不是创建一个新线程,而不是像:

executor.submit(grafter)

这应该可以帮到你,但如果你想让服务迅速干净地关闭,你可以做更多的事情。 shmosel在评论中提供的链接可以帮助您。

顺便说一下,你做这件事的方式并不是非常有效我不会想到的。基本上,您为字典中的每个单词创建一个新任务,这意味着您有大量任务(在您的情况下为100K)。这意味着管理和安排所有这些任务的开销很可能是您的程序执行的工作的重要部分。相反,您可能希望将单词列表分成若干个子列表,每个子列表包含相同数量的单词,然后使您的可运行进程仅包含子列表。