代码之家  ›  专栏  ›  技术社区  ›  Questioner

由多个线程并行计算哈希,并将输出添加到ArrayList<String>

  •  0
  • Questioner  · 技术社区  · 3 年前

    为了计算 String (基于SHA-256),然后将所有输出插入 ArrayList<String> :

            ArrayList<Thread> threadList = new ArrayList<Thread>();
            ArrayList<String> threadListStr = new ArrayList<String>();
            int threadNumber = 100;
            for (int i = 0; i < threadNumber; i++) {
                String tId = String.valueOf(i);
                Thread thr = new Thread(() -> {
                    threadListStr.add(calculateHash(tId));
                });
                threadList.add(thr);
            }
    
            // START the threads
            for (int i = 0; i < threadNumber; i++) {
                threadList.get(i).start();
            }
            // STOP the threads
            for (int i = 0; i < threadNumber; i++) {
                threadList.get(i).interrupt();
            }
    
            System.out.println("Size of ArrayList<String> is: " + threadListStr.size());
            System.out.println("Size of ArrayList<Thread> is: " + threadList.size());
            
            /////////////////////
            
            public static String calculateHash(String tId) {
            String tIdStr = org.apache.commons.codec.digest.DigestUtils.sha256Hex(tId);
            return tIdStr;
            }
    

    但是,ArrayList并不完整,正如您在运行代码5次后看到的,每次ArrayList都有不同的大小(尽管ArrayList线程列表总是完整的,因为线程数是100)

    //1th run
    Size of ArrayList<String> is: 60
    Size of ArrayList<Thread> is: 100
    
    //2nd run
    Size of ArrayList<String> is: 30
    Size of ArrayList<Thread> is: 100
    
    //3rd run
    Size of ArrayList<String> is: 10
    Size of ArrayList<Thread> is: 100
    
    //4th run
    Size of ArrayList<String> is: 61
    Size of ArrayList<Thread> is: 100
    
    //5th
    Size of ArrayList<String> is: 69
    Size of ArrayList<Thread> is: 100
    

    应该如何修改代码,以便 ArrayList<字符串> 商店 全部的 输出 彻底地 ?

    伊迪特: 我对代码做了如下更改,但输出是一样的。

            ArrayList<Thread> threadList = new ArrayList<Thread>();
            //ArrayList<String> threadListStr = new ArrayList<String>();
            List<String> threadListStrSync = Collections.synchronizedList(new ArrayList<>());
            int threadNumber = 100;
            for (int i = 0; i < threadNumber; i++) {
                String tId = String.valueOf(i);
                Thread thr = new Thread(() -> {
                    threadListStrSync.add(calculateHash(tId));
                });
                threadList.add(thr);
            }
    
            // START the threads
            for (int i = 0; i < threadNumber; i++) {
                threadList.get(i).start();
            }
            // STOP the threads
            for (int i = 0; i < threadNumber; i++) {
                threadList.get(i).interrupt();
            }
    
            System.out.println("Size of ArrayList<String> is: " + threadListStrSync.size());
            System.out.println("Size of ArrayList<Thread> is: " + threadList.size());
    

    注: 我评论道 interrupt(); 但产出仍然是一样的。

    0 回复  |  直到 3 年前
        1
  •  1
  •   Hulk    3 年前

    有很多问题

    1. 使用threadsafe集合或手动同步访问——一个简单的选择是用 Collections.synchronizedList()
    2. interrupt() 如果不需要,线程将在到达任务末尾时终止 run() -方法
    3. 在打印结果之前,需要等待所有线程终止——为此,请调用 join() 而不是 中断()
        2
  •  0
  •   Dave S    3 年前

    您有两个问题:1)可能有一些线程在执行过程中始终无法将其哈希ID添加到集合中,2)哈希ID的集合正被多个线程访问,因此您应该使用线程安全的集合。

        ArrayList<Thread> threadList = new ArrayList<Thread>();
        Collection<String> threadListStr = Collections.synchronizedCollection( new ArrayList<String>() );
        int threadNumber = 100;
        for (int i = 0; i < threadNumber; i++) {
            String tId = String.valueOf(i);
            Thread thr = new Thread(() -> {
                threadListStr.add(calculateHash(tId));
            });
            threadList.add(thr);
        }
    
        // START the threads
        for (int i = 0; i < threadNumber; i++) {
            threadList.get(i).start();
        }
        // STOP the threads
        for (int i = 0; i < threadNumber; i++) {
           try {
               threadList.get(i).join();
           } catch( InterruptedException exc ) {
               // handle interrupted exception
           }
        }
    
        System.out.println("Size of ArrayList<String> is: " + threadListStr.size());
        System.out.println("Size of ArrayList<Thread> is: " + threadList.size());