java - 未能使我的 ArrayList 成为线程安全的。线程中的异常 "main"java.lang.ClassCastException : What is wrong?

标签 java multithreading arraylist collections brute-force

我决定优化下面的代码,但遇到了问题。我尝试使用 this discussion 将 ArrayList 更改为线程安全集合但不幸的是出了问题。代码正在编译,但抛出异常。

Exception in thread "main" java.lang.ClassCastException: java.util.Collections$SynchronizedRandomAccessList cannot be cast to java.util.ArrayList at bfpasswrd_multi.PasswordCracker.doItMulti(PasswordCracker.java:73) at bfpasswrd_multi.PasswordCracker.runMulti(PasswordCracker.java:60) at bfpasswrd_multi.Test.main(Test.java:16)

请告诉我出了什么问题?

package bfpasswrd_multi;


  import java.util.Scanner;

  public class Test

  {
    public static void main(String[] args)
    {

    System.out.print("Type password to be cracked: ");
    @SuppressWarnings("resource")
    String input = new Scanner(System.in).nextLine();
    PasswordCracker cracker = new PasswordCracker();
    System.out.println("Multithreaded");
    cracker.runMulti(input);
    cracker = new PasswordCracker();


    System.out.println("Finished...");
    }
}
<小时/>
package bfpasswrd_multi;

import java.util.ArrayList;
import java.util.Collections;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;


public class PasswordCracker
{

String passwordToCrack;
public boolean passwordFound;
int min;
int max;
StringBuffer crackedPassword;

public void prepare(String text)
{
    passwordToCrack = text;

    passwordFound = false;
    min = 48;
    max = 57;                               // http://ascii.cl/
    crackedPassword = new StringBuffer();
    crackedPassword.append((char) (min - 1));           
}

public void result()
{
    System.out.println("Cracked Password is: " + crackedPassword.toString());
}

public void incrementString(StringBuffer toCrack, int min, int max)
{
    toCrack.setCharAt(0, (char) ((int) toCrack.charAt(0) + 1));
    for (int i = 0; i < toCrack.length(); i++)
    {
        if (toCrack.charAt(i) > (char) max)
        {
            toCrack.setCharAt(i, (char) min);
            if (toCrack.length() == i + 1)
            {
                toCrack.append((char) min);
            }
            else
            {
                toCrack.setCharAt(i + 1, (char) ((int) toCrack.charAt(i + 1) + 1));
            }
        }
    }
}

public void runMulti(String text)
{
    prepare(text);
    double time = System.nanoTime();
    doItMulti();
    time = System.nanoTime() - time;
    System.out.println(time / (1000000000));
    result();

}


public void doItMulti()
{
    int cores = Runtime.getRuntime().availableProcessors();
     ArrayList<Future<?>> tasks ;           // How do I make my ArrayList Thread-Safe? Another approach to problem in Java?
                                        // https://stackoverflow.com/questions/2444005/how-do-i-make-my-arraylist-thread-safe-another-approach-to-problem-in-java
    tasks =   (ArrayList<Future<?>>) Collections.synchronizedList(new ArrayList<Future<?>>(cores));
  //   ArrayList<Future<?>> tasks = new ArrayList<>(cores);
    ExecutorService executor = Executors.newFixedThreadPool(cores);
    final long step = 2000;
    for (long i = 0; i < Long.MAX_VALUE; i += step)
    {
        while(tasks.size() > cores)
        {
            for(int w = 0; w < tasks.size();w++)
            {
                if(tasks.get(w).isDone())
                {
                    tasks.remove(w);
                    break;
                }
            }
            try
            {
                Thread.sleep(0);
            }
            catch (InterruptedException e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        {
            final long j = i;
            if (passwordFound == false)
            {
                tasks.add(executor.submit(new Runnable()
                {

                    public void run()
                    {
                        long border = j + step;
                        StringBuffer toCrack = new StringBuffer(10);
                        toCrack.append(constructString3(j, min, max));
                        for (long k = j; k < border; k++)
                        {
                            incrementString(toCrack, min, max);
                            boolean found = toCrack.toString().equals(passwordToCrack);
                            if (found)
                            {
                                crackedPassword = toCrack;
                                passwordFound = found;
                                break;
                            }
                        }
                    }
                }));
            }
            else
            {
                break;
            }
        }
    }
    executor.shutdownNow();
}

public String constructString3(long number, long min, long max)
{

    StringBuffer  text = new StringBuffer();        
    if (number > Long.MAX_VALUE - min)              
    {
        number = Long.MAX_VALUE - min;              
    }                                                

    ArrayList<Long> vector = new ArrayList<Long>(10);
    vector.add(min - 1 + number);
    long range = max - min + 1;
    boolean nextLetter = false;
    for (int i = 0; i < vector.size(); i++)
    {
        long nextLetterCounter = 0;
        while (vector.get(i) > max)
        {
            nextLetter = true;
            long multiplicator = Math.abs(vector.get(i) / range);
            if ((vector.get(i) - (multiplicator * range)) < min)
            {
                multiplicator -= 1;
            }
            vector.set(i, vector.get(i) - (multiplicator * range));
            nextLetterCounter += multiplicator;
        }
        if (nextLetter)
        {
            vector.add((long) (min + nextLetterCounter - 1));
            nextLetter = false;
        }
        text.append((char) vector.get(i).intValue());
    }
    return text.toString();
}
}

提前非常感谢!

最佳答案

您看到的问题与此行有关:

tasks =   (ArrayList<Future<?>>) Collections.synchronizedList(new ArrayList<Future<?>>(cores));

Collections.synchronizedList不返回 ArrayList ;它返回 List 的某个子类-java.util.Collections$SynchronizedRandomAccessList确切地说,除了 List 之外,我对这个类一无所知。 ,但它不是 ArrayList .

解决这个问题的简单方法是声明 tasks成为List<Future<?>> :

List<Future<?>> tasks =
    Collections.synchronizedList(new ArrayList<Future<?>>(cores));

关于java - 未能使我的 ArrayList 成为线程安全的。线程中的异常 "main"java.lang.ClassCastException : What is wrong?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37799270/

相关文章:

java - Spring Boot 应用部署到 Heroku 与谷歌云 Mysql

c - 为什么使用 numa_alloc_onnode() 进行分配会导致 "The page is not present"?

c - errno 是线程安全的吗?

java - ArrayList不会显示其元素

java - 在 ArrayList Java 中搜索特定对象

java - 摆脱 "No Hibernate Session bound to thread"并在读取方法上使用 @Transactional 进行性能

java - 如何在java中制作分层Json

java - 如何编写一个按键监听器来跟踪 Java 中的所有击键?

Java 任务在循环后停止

java - Java中分割ArrayList并将其传递给不同的线程