有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

多线程无法使我的ArrayList线程安全。线程“main”java中出现异常。例外:怎么了?

我决定优化下面的代码,但遇到了问题。我试图使用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();
}
}

非常感谢


共 (2) 个答案

  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();
    }
    }
    
  2. # 2 楼答案

    你看到的问题是这句话:

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