无法使我的ArrayList线程安全。线程" main"中的例外情况java.lang.ClassCastException:有什么问题?

时间:2016-06-13 21:15:51

标签: java multithreading arraylist collections brute-force

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

  

线程中的异常" main" java.lang.ClassCastException:   java.util.Collections $ SynchronizedRandomAccessList无法强制转换为   java.util.ArrayList at   bfpasswrd_multi.PasswordCracker.doItMulti(PasswordCracker.java:73)at 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();
}
}

非常感谢提前!

2 个答案:

答案 0 :(得分:1)

您所看到的问题是这一行:

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));

答案 1 :(得分:1)

亲爱的社区成员感谢您的评论。现在我的安全线程列表似乎正在运行。对于有兴趣解决方案的人,我将在下面提交已解决的代码。另外,我应该提一下,我重命名任务期货,请注意。大家再次感谢!

package bfpasswrd_multi;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
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<?>> task;            // HOW IT WAS 
                                            // 
  //  tasks =   (ArrayList<Future<?>>) Collections.synchronizedList(new ArrayList<Future<?>>(cores));                   // HOW IT WAS 
    List<Future<?>>  futures ;              // THE SOLUTION 
    futures =   Collections.synchronizedList(new ArrayList<Future<?>>(cores));                                       // THE SOLUTION 


  //   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(futures.size() > cores)
        {
            for(int w = 0; w < futures.size();w++)
            {
                if(futures.get(w).isDone())
                {
                    futures.remove(w);
                    break;
                }
            }
            try
            {
                Thread.sleep(0);
            }
            catch (InterruptedException e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        {
            final long j = i;
            if (passwordFound == false)
            {
                futures.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();
}
}