【问题标题】:Multithreading Java- Threads clashing/overwriting issue多线程 Java-线程冲突/覆盖问题
【发布时间】:2016-02-21 11:32:29
【问题描述】:

我正在使用一个简单的线程池来读取一个大字典arraylist 到单个线程来处理。

当数组列表中有 500 个单词时,它会将其存储在“单词”类的实例中。这只是存储并允许访问 arrayList(分配给该线程的 arrayList)。

这似乎不起作用,因为有重复项,而且大多数时候字典中的最后 500 个单词都是所有线程最终使用的,我觉得很奇怪。此外,我还注意到,当我在下面显示的 for 循环的内部添加一个简单的 3 秒超时时,它可以工作,但这似乎是一个可怕的修复,我希望这个程序尽可能高效和快速。

// Executor Program
ExecutorService executor = Executors.newFixedThreadPool(cores);
    ArrayList<String> words123 = new ArrayList<String>();
    for (int i = 0; i < dictionary.size(); i++) {
        words123.add(dictionary.get(i));
        if(words123.size() == 1000) {
            Words wordsList = new Words(words123);
            Runnable worker = new WorkerThread(wordsList, passwords, stp);
            executor.execute(worker);
            words123 = new ArrayList<String>();
        }
    }
    executor.shutdown();
    //wait for all jobs to complete
    while (!executor.isTerminated()) {
    }
    System.out.println("Finished all threads");




// WORD OBJECT ------------------
public class Words {
public static ArrayList<String> words = new ArrayList<String>();

public Words(ArrayList words) {
    this.words = words;
}

public int getSize() {
    return words.size();
}

public String getWord(int i) {
    return words.get(i);
}

}

//WORKER THREAD ----------------

    public static Words wordList;
public static int cmd;
public static HashMap<String, String> passwords = new HashMap<String, String>();
public static SimpleThreadPool stp;
/**
 * Constructor
 * @param s
 */
public WorkerThread(Words word, HashMap passwords, SimpleThreadPool stp, int cmd){
    this.wordList = word;
    //System.out.println("in  " + words);
    //Read in hashes using readFromFile method
    this.passwords = passwords;
    this.stp = stp;
    this.cmd = cmd;
}

/**
 * For a thread pool to function, ensure that the run() method terminates
 * This method prints out the command, calls a function, then prints end and terminates
 */
@Override
public void run() {
    //System.out.println(Thread.currentThread().getName()+" Start.");
    //System.out.println("WOOOO  " + wordList.getWords() + cmd);

    for(int i = 0; i < wordList.getSize(); i++){
        Password pass = new Password(wordList.getWord(i), hashPassword(wordList.getWord(i)));
        //System.out.println(pass.getOriginalPass());
        //checkHash(pass);

        // Check password with letter-number edits (e.g. a-->@)
        letterSymbolEdit(pass);

        // Check password with capital letter edits
        //capitalsEdit(pass);

        // Reverse password
        reverseEdit(pass);

        // Concatenate all words in dictionary
        //concatEdit(pass);

        printPermutations(pass);

        // All possible numbers generated and appended to string
        for(int j = 0; j < 4; j++){
            numberBuilder("", 0, j, pass);
        }
    }
    //System.out.println(Thread.currentThread().getName()+" End.");
}

【问题讨论】:

  • 你能发一个minimal reproducible example吗?
  • 你能用Vector代替arrayList吗?我相信向量可以用于同步操作。
  • 请至少向我们展示您的WordsWorkerThread 课程
  • @may 这真的是问题吗?就我将数组列表传递给类的新实例而言,它们的实例将如何覆盖。

标签: java multithreading dictionary arraylist threadpool


【解决方案1】:

问题在于 Words 类中的“单词”变量是静态的,这意味着该类的每个实例都使用相同的列表。

另外,由于您想提高效率,我会使用不同的方法。而不是

ExecutorService executor = Executors.newFixedThreadPool(cores);

使用

LinkedBlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>();
ThreadPoolExecutor executor = new ThreadPoolExecutor(cores, cores, 0L, TimeUnit.MILLISECONDS, workQueue);
executor.prestartAllCoreThreads();

然后将 Runnable 实例直接添加到 workQueue。通过这种方式,您不必等待自己在线程之间划分单词:线程将在完成任务后立即获取它们。

【讨论】:

  • 非常感谢!犯了非常业余的错误,为此工作了几个小时,谢谢! :)
  • 啊,谢谢,它需要尽可能快,所以我从我的问题中删除了我在示例中实现的 Words 类,现在只需将 arrayList 传递给通过实例发送到类包含该线程的arraylist,你会说这也更有效吗?也感谢您现在尝试的建议:)
  • 由于您已经拥有一个线程池,它有权在其线程之间分配工作,因此无需构建单词子列表:您可以实现每个 Runnable 只处理一个单词。另外,我刚刚注意到,如果您的 dictionary.size() 不是 1000 的倍数会怎样?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多