简体   繁体   English

如何使用多线程加速代码?

[英]How to speed up code with Multithreading?

I have created a password cracker in Java that cracks passwords from a text file list.我用 Java 创建了一个密码破解程序,它可以破解文本文件列表中的密码。 It then generates a dictionary that contains the following pairs: the word hashed and the original word.然后它生成一个包含以下对的字典:散列的单词和原始单词。 I am looking for a way to speed up the program as having it read all of the words from the file and then use multithreading to generate the hashes.我正在寻找一种方法来加速程序,让它从文件中读取所有单词,然后使用多线程生成哈希。 How can I break up the list of words so that it is in four separate partitions that I can then have multiple threads operate on in the createDictionary method?如何分解单词列表,使其位于四个单独的分区中,然后我可以在 createDictionary 方法中对多个线程进行操作? Here is what I have so far:这是我到目前为止所拥有的:

public class Main {
    private static final String FNAME = "words.txt";
    private final static String PASSWDFNAME = "passwd.txt";
    private static Map<String, String> dictionary = new HashMap<>();

    public static void main(String[] args) {
        // Create dictionary of plain / hashed passwords from list of words
        System.out.println("Generating dictionary ...");
        long start = System.currentTimeMillis();
        createDictionary(FNAME);
        System.out.println("Generated " + dictionary.size() + " hashed passwords in dictionary");
        long stop = System.currentTimeMillis();
        System.out.println("Elapsed time: " + (stop - start) + " milliseconds");
        
        // Read password file, hash plaintext passwords and lookup in dictionary
        System.out.println("\nCracking password file ...");
        start = System.currentTimeMillis();
        crackPasswords(PASSWDFNAME);
        stop = System.currentTimeMillis();
        System.out.println("Elapsed time: " + (stop - start) + " milliseconds");
    }
    
    private static void createDictionary(String fname) {
        // Read in list of words
        List<String> words = new ArrayList<>();
        try (Scanner input = new Scanner(new File(fname));) {
            while (input.hasNext()) {
                String s = input.nextLine();
                if (s != null && s.length() >= 4) {
                    words.add(s);
                }
            }
        } catch (FileNotFoundException e) {
            System.out.println("File " + FNAME + " not found");
            e.printStackTrace();
            System.exit(-1);
        }
        
        // Generate dictionary from word list
        for (String word : words) {
            generateHashes(word);
        }
    }
    
    private static void crackPasswords(String fname) {
        File pfile = new File(fname);
        try (Scanner input = new Scanner(pfile);) {
            while (input.hasNext()) {
                String s = input.nextLine();
                String[] t = s.split(",");
                String userid = t[0];
                String hashedPassword = t[1];
                String password = dictionary.get(hashedPassword);
                if (password != null) {
                    System.out.println("CRACKED - user: "+userid+" has password: "+password);
                }
            }
        } catch (FileNotFoundException ex) {
            System.out.println(ex.getMessage());
            ex.printStackTrace();
            System.exit(-1);
        }
    }

    private static void generateHashes(String word) {
        // Convert word to lower case, generate hash, store dictionary entry
        String s = word.toLowerCase();
        String hashedStr = HashUtils.hashPassword(s);
        dictionary.put(hashedStr, s);
        // Capitalize word, generate hash, store dictionary entry
        s = s.substring(0, 1).toUpperCase() + s.substring(1);
        hashedStr = HashUtils.hashPassword(s);
        dictionary.put(hashedStr, s);
    }
}

It's very simple, check this out:很简单,看看这个:

public static void main(String[] args) {
    List<String> words = new ArrayList<>();
    List<Thread> threads = new ArrayList<>();

    int numThreads = 4;
    int threadsSlice = words.size() / numThreads;

    for(int i = 0; i < numThreads; i++) {
        Thread t = new Thread(new WorkerThread(i * threadsSlice, (i + 1) * threadsSlice, words));
        t.start();
        threads.add(t);
    }

    threads.forEach(t -> {
        try {
            t.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    });
}

static class WorkerThread implements Runnable {
    private final int left;
    private final int right;
    private final List<String> words;

    public WorkerThread(int left, int right, List<String> words) {
        this.left = left;
        this.right = right;
        this.words = words;
    }

    @Override
    public void run() {
        for (int i = left; i < right; i++) {
            generateHashes(words.get(i));
        }
    }
}

This code is creating 4 threads, each one scanning one partition of your list, and applying the generateHashes method on all the words in the partition.这段代码创建了 4 个线程,每个线程扫描列表的一个分区,并对分区中的所有单词应用generateHashes方法。

You can put the words in the heap memory to avoid passing it to each thread via constructor param.您可以将words放在堆内存中,以避免通过构造函数参数将其传递给每个线程。

Also make sure to use a ConcurrentMap for your dictionary in the generateHashes method还要确保在generateHashes方法中为您的字典使用ConcurrentMap

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM