【问题标题】:java multithreaded hashed ArrayList<String>java 多线程散列 ArrayList<String>
【发布时间】:2015-07-27 12:39:42
【问题描述】:

我想对 arraylist 中的每个项目进行哈希处理,然后基本上将其返回到 main 中。但例如一个有这个:

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;

public class hash extends Thread {

    private Thread t = null;
    private MessageDigest md = null;
    private StringBuffer sb = null;
    private String message = null;
    private ArrayList<String> list = null;
    private int count = 0;

    public hash(ArrayList<String> list) {
        this.list = list;
    }

    public final void mdstart() {

        for(String item:list){
            this.message=item;
            if(t==null){
                t = new Thread(this);
                t.start();
            }
            count++;
        }
        System.out.println("end: "+this.count);

    }

    @Override
    public final void run() {
        System.out.println("run: "+this.count);
        try {
            md = MessageDigest.getInstance("MD5");
            md.update(this.message.getBytes());

            byte[] digest = md.digest();
            sb = new StringBuffer();
            for (byte hash : digest) {
                sb.append(String.format("%02x", hash));
            }
            System.out.println(this.message + " : " + sb.toString());
        } catch (NoSuchAlgorithmException ex) {
            System.out.println("no such algorithm exception : md5");
            System.exit(1);
        }
    }

    public static void main(String args[]) {

        ArrayList<String> list = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            list.add("message" + i);
        }
        new hash(list).mdstart();      
    }
}

输出是:

end: 10
run: 10
message9 : 99f72d2de922c1f14b0ba5e145f06544

这意味着程序只运行我期望的最后一个线程。

【问题讨论】:

    标签: java multithreading arraylist


    【解决方案1】:

    您将线程存储在t 中,它在开始时为空,但在创建第一个线程后,它不再为空,因此您的 if 失败并且没有创建新线程。然后您尝试在此线程运行时修改消息...老实说,整个事情都是一团糟。即使您要创建 10 个线程,它们都将指向同一个 hash() 对象,其中消息变量随机更改,而不知道是否有任何线程已经完成工作。

    例如,可能会发生以下情况:

    1. 您为第一条消息启动线程
    2. 线程尚未运行,但您的 for 循环已将消息设置为第二个
    3. 线程运行并计算第二条消息的消息
    4. 消息 3 已设置。由于 Thread 已经完成,因此没有任何反应。
    5. 消息 4 再次设置,线程完成后没有任何反应 等

    修复它:

    • 从哈希中删除列表变量。
    • 为每个哈希码/消息创建一个新的 hash() 对象
    • 为每个 hash() 对象启动一个新线程。然后它应该工作。

    【讨论】:

    • 我还要添加将 hash 类的父类更改为 Runnable 而不是 Thread,因为它本身从未用作 Thread
    【解决方案2】:

    问题是你的代码只会启动一个线程:

    if(t==null){
        t = new Thread(this);
        t.start();
    }
    

    一旦启动第一个线程,t 就不再是null,因此不会创建新线程。

    要解决此问题,请创建一个线程数组,并将threads[count++] 设置为循环中新创建的线程。循环结束后,您可以join 您的线程以确保它们在mdstart() 返回之前全部完成:

    public final void mdstart() {
        Thread[] threads = new Thread[list.size()];
        for(String item:list){
            this.message=item;
            threads[count] = new Thread(this);
            threads[count].start();
            count++;
        }
        for (Thread t : threads) {
            t.join();
        }
        System.out.println("end: "+this.count);
    }
    

    注意:这将修复代码的启动部分。您需要在 run() 方法中处理同步问题才能完成修复。

    【讨论】:

    • 我怀疑这会有所帮助,因为他正在随机更改this 中的消息,并且所有线程都将访问相同的this 对象...
    • @FlorianSchaetz 绝对 - 这只会确保启动十个线程。它不会解决 OP 的同步问题。
    • 感谢您的帮助,我明白自己犯了一些严重的错误。你能给我推荐一些链接来阅读更多关于线程的信息吗?
    • @sifis 除了 Oracle 提供的 (link) 之外,我想不出一本好书或教程,但您可能已经完成了它。
    猜你喜欢
    • 2016-05-31
    • 2017-08-30
    • 2011-01-24
    • 2018-11-09
    • 1970-01-01
    • 2012-08-31
    • 2016-02-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多