2016-06-13 5 views
0

아래 코드를 최적화하기로 결정했지만 문제가 발생했습니다. this discussion을 사용하여 ArrayList를 스레드로부터 안전한 컬렉션으로 변경하려고 시도했지만 불행히도 문제가 발생했습니다. 코드가 컴파일되지만 예외가 발생합니다. 스레드 "주요"java.lang.ClassCastException가에내 ArrayList를 Thread-Safe로 만들지 못했습니다. 스레드 "main"의 예외 java.lang.ClassCastException : 무엇이 잘못 되었습니까?

예외 : Collections의 $ SynchronizedRandomAccessList이 bfpasswrd_multi.PasswordCracker.doItMulti (PasswordCracker.java:73)에서 인 java.util.ArrayList 캐스트 할 수없는 bfpasswrd_multi.Test.main (Test.java:16)

십시오 bfpasswrd_multi.PasswordCracker.runMulti (PasswordCracker.java:60)에서, 무엇이 잘못되었는지 말해? 사전에


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

많은 감사합니다!

+1

동기화 된 목록은 'ArrayList'가 아닙니다. 당신은 그 던지기를 할 수 없습니다. 'tasks '를'List > tasks;로 선언하십시오. –

+0

나는 그 변수의 이름도 바꿀 것이다. "태스크"는 실행자 서비스에 제출하는 것이고 _future_는 다시 얻는 것입니다. 'tasks '대신'futures' 변수의 이름을 짓겠습니다. –

+0

작동하는 것처럼 보입니다. 고마워. 오키, 나는 이름을 바꾸고 해결책을 제출한다. 당신이 말했어 고마워요. 빨리. 어쩌면 다른 최적화, 제발 말해 자유롭게. 당신의 의견은 많이 감사하겠습니다! –

답변

1

당신이보고있는이 문제는이 라인이다 : ArrayList를 반환하지 않습니다

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

Collections.synchronizedList; List - java.util.Collections$SynchronizedRandomAccessList의 일부 하위 클래스를 반환합니다.이 클래스는 List 이외의 클래스에 대해서는 아무것도 모릅니다 만, ArrayList이 아닙니다. 귀하의 의견에 대한

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

친애하는 지역 사회 구성원 덕분에 당신은 :

이에 대한 쉬운 해결책은 List<Future<?>>tasks을 선언하는 것입니다. 이제 내 안전 스레드 목록이 작동하고있는 것처럼 보입니다. 흥미로운 사람들을 위해 아래 해결 된 코드를 제출할 것입니다. 또한 아마도 나는 작업의 이름을 to future으로 변경해야한다고 언급해야 할 것입니다. 다시 한번 모두 감사합니다!

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