2012-09-29 5 views
0

테스트중인 번호가 행복한 숫자이면 1을 출력하고 그렇지 않으면 0을 출력하는 코드를 작성했습니다.주 스레드가 중단되지 않습니다

class Ishappy extends Thread { 
    private Integer num; 
    private Thread main; 
    private volatile boolean out = false; 

    Ishappy(int i, Thread main) { 
     this.main = main; 
     num = i; 
    } 

    void Exit() { 
     out = true; 
    } 

    @Override 
    public void run() { 
     while(!out && num != 1) { 
      if(num == 1) { 
       main.interrupt(); 
       break; 
      } 

      String s = num.toString(); 
      int temp = 0; 
      for(int i = 0 ; i < s.length(); i++) { 
       int x = Integer.parseInt(s.substring(i, i+1)); 
       temp += x*x; 
      } 
      num = temp; 
     } 
    } 
} 

public class Happy_numbers { 
    public static void main(String[] args) { 
     byte path[] = null; 

     String s = "d:\\data.txt"; 

     try(FileInputStream fin = new FileInputStream(s)) { 
      InputStreamReader in = new InputStreamReader(fin); 
      BufferedReader br = new BufferedReader(in); 
      s = br.readLine(); 
      int num; 
      while(s != null) { 
       num = Integer.parseInt(s); 

       Ishappy ishappy = new Ishappy(num,Thread.currentThread()); 
       ishappy.start(); 
       try { 
        Thread.sleep(1000); 
       } catch (InterruptedException ex) { 
        System.out.println(1); 
        continue; 
       } 
       if(ishappy.isAlive()) { 
        ishappy.Exit(); 
        System.out.println(0); 
       } else 
        System.out.println(11); 

       s = br.readLine(); 
      } 
     } catch (FileNotFoundException ex) { 
      System.out.println("File not found."); 
     }catch(IOException ex){ 
     } 
    } 
} 

하지만 위의 코드는 항상 중단되지 지 않습니다 main을 의미 행복 번호 (11)를 인쇄합니다. 뭐가 문제 야?? data.txt로의

내용은 (1)의 가운데

1 
7 
22 

을하고 22없는 반면 7 행복 수있다.

+0

귀하의 코드가이 클래스와 메소드의 이름을 지정하는 방식으로 인정 된 자바 코딩 표준을 위반입니다. 클래스 이름에는''_ ''문자가 포함되어서는 안되며 "camel case"를 사용해야하며 메서드 이름은 대문자로 시작하면 안됩니다. –

+0

내 코드를 변경했습니다. 자본 'e'는 실제로 조금 공격적이었습니다. 내가 '-'를 사용하고있는 것은 파일의 이름을 유지하도록 요청 받았기 때문입니다. :) – user1232138

답변

0

여기에 스레딩 할 필요가 없습니다. 제곱의 제곱의 합이 1이면 행복 할 수 있습니다. 시퀀스에 이미 테스트 된 번호가 포함되어있는 경우 그냥 끝내라. n이 행복하지 않은 경우 위키 피 디아에서

, 다음의 순서는 대신 발생이주기에 끝나는 무엇 1로 이동하지 않습니다.

public class Happy_numbers {   
    static int[]SQUARES={0,1,4,9,16,25,36,49,64,81}; 
    public static boolean is_happy(int n){ 
     return is_happy(n, new HashSet<Integer>()); 
    } 
    public static boolean is_happy(int n, Collection<Integer> sofar){ 
     if(n==1) return true; 
     else if(sofar.contains(n)) return false; 

     sofar.add(n); 

     if(n<10) { 
      return is_happy(SQUARES[n], sofar); 
     } 

     char[]digits=String.format("%s", n).toCharArray(); 
     int s = 0; 
     for(char c:digits){ 
      s+= SQUARES[Integer.valueOf(String.format("%s", c))]; 
     } 

     return is_happy(s, sofar); 
    } 
    public static void main(String[]args){ 
     Collection<Integer> c1 = Arrays.asList(
       1, 7, 10, 13, 19, 23, 28, 31, 32, 44, 49, 68, 70, 79, 82, 86, 91, 94, 97, 
       100, 103, 109, 129, 130, 133, 139, 167, 176, 188, 190, 192, 193, 203, 208, 
       219, 226, 230, 236, 239, 262, 263, 280, 291, 293, 301, 302, 310, 313, 319, 
       320, 326, 329, 331, 338, 356, 362, 365, 367, 368, 376, 379, 383, 386, 391, 
       392, 397, 404, 409, 440, 446, 464, 469, 478, 487, 490, 496); 
     Collection<Integer> c2 = new ArrayList<Integer>(c1.size()); 
     long t = System.currentTimeMillis(); 
     int c = 1; 
     for(int i=0;i<500;i++){ 
      if(is_happy(i)) { 
       System.out.print(i+", "); 
       if(c++ % 20 == 0) System.out.println(); 
       c2.add(i); 
      } 

     } 
     t = System.currentTimeMillis()-t; 
     System.out.println("\nTIME : " + t); 
     System.out.println("Got them all < 500 : " + (c2.containsAll(c1) && c1.containsAll(c2))); 
    } 
} 

또한 더 많은 행복이고 당신이 번호 앞에 계산 한 경우, 필요 다시 같은 일을하지 할 수 있도록지도, 또는 캐싱 기술을 사용하여 향상시킬 수있다. wikipediea에서 500 이하

행복 번호는 : 1, 7, 10, 13, 19, 23, 28, 31, 32, 44, 49, 68, 70, 79, 82, 86, 91 , 94, 97, 100, 103, 109, 129, 130, 133, 139, 167, 176, 188, 190, 192, 193, 203, 208, 219, 226, 230, 236, 239, 262, 263 328, 356, 362, 365, 367, 368, 376, 379, 383, 386, 391, 392, 397, 404, 409, 440, 446, 464, 469, 478, 487, 490, 496 (OEIS 내의 서열 A007770).

및 위의 코드는 그래서 500

1, 7, 10, 13, 19, 23, 28, 31, 32, 44, 49, 68, 70, 79, 82, 86, 91, 94, 97, 100, 
103, 109, 129, 130, 133, 139, 167, 176, 188, 190, 192, 193, 203, 208, 219, 226, 230, 236, 239, 262, 
263, 280, 291, 293, 301, 302, 310, 313, 319, 320, 326, 329, 331, 338, 356, 362, 365, 367, 368, 376, 
379, 383, 386, 391, 392, 397, 404, 409, 440, 446, 464, 469, 478, 487, 490, 496, 
TIME : 435 
Got them all < 500 : true 

아래 모든 행복 번호를 얻기 위해 435 필요, 나는 적어도 지금까지 계산 된 것을 기억 허용하도록 코드를 일부 변경 한 현재 번호

public class Happy_numbers { 

    static class Ishappy extends Thread { 
     private Integer num; 
     private Thread main; 
     private volatile boolean out = false; 

     private boolean unhappy = false; 

     Ishappy(int i, Thread main) { 
      this.main = main; 
      num = i; 
     } 

     public boolean isUnhappy() { 
      return unhappy; 
     } 

     void Exit() { 
      out = true; 
     } 

     @Override 
     public void run() { 
      Set<Integer> sofar = new HashSet<Integer>(); 
      while(!out && num != 1) { 
       unhappy = sofar.contains(num); 
       if(num == 1 || unhappy) { 
        main.interrupt(); 
        break; 
       } 

       sofar.add(num); 

       String s = num.toString(); 
       int temp = 0; 
       for(int i = 0 ; i < s.length(); i++) { 
        int x = Integer.parseInt(s.substring(i, i+1)); 
        temp += x*x; 
       } 
       num = temp; 
      } 
     } 
    } 

    public static void main(String[] args) throws Exception{ 
     byte path[] = null; 

     String s = "./data.txt"; 

     FileInputStream fin = new FileInputStream(s); 
     InputStreamReader in = new InputStreamReader(fin); 
     BufferedReader br = new BufferedReader(in); 
     int num; 
     while((s = br.readLine()) != null) { 
      num = Integer.parseInt(s); 

      Ishappy ishappy = new Ishappy(num,Thread.currentThread()); 
      ishappy.start(); 
      ishappy.join(); 
      if(ishappy.isUnhappy()){ 
       System.out.println("Number ["+num+"] is not happy"); 
      }else{ 
       System.out.println("Number ["+num+"] is happy"); 
      } 
     } 
     br.close(); 
     in.close(); 
     fin.close(); 
    } 
} 

출력 내가 메인 스레드 나던이 중단 얻을 이유를 발견

Number [1] is happy 
Number [7] is happy 
Number [22] is not happy 

편집

입니다.

메인 while 루프에서 num이 1인지 확인합니다. 하나 인 경우 num 값을 확인하고 기본 스레드를 인터럽트하는 if 조건을 얻지 못합니다. 여기

public class Happy_numbers { 
    public static void main(String[] args) throws IOException{ 

     String s = "./data.txt"; 

     FileInputStream fin = new FileInputStream(s); 
     InputStreamReader in = new InputStreamReader(fin); 
     BufferedReader br = new BufferedReader(in); 
     int num; 
     while((s = br.readLine()) != null) { 
      num = Integer.parseInt(s); 

      Ishappy ishappy = new Ishappy(num,Thread.currentThread()); 
      ishappy.start(); 
      try { 
       Thread.sleep(1000); 
      } catch (InterruptedException ex) { 
       System.out.println(1); 
       continue; // here is another problem, infinit loop 
      } 
      if(ishappy.isAlive()) { 
       ishappy.Exit(); 
       System.out.println(0); 
      } else 
       System.out.println(11); 

     } 
     br.close(); 
     in.close(); 
     fin.close(); 
     System.out.println("DONE"); 
    } 
} 

는 Ihappy 클래스

class Ishappy extends Thread { 
    private volatile Integer num; 
    private Thread main; 
    private volatile boolean out = false; 

    Ishappy(int i, Thread main) { 
     this.main = main; 
     num = i; 
    } 

    void Exit() { 
     out = true; 
    } 

    @Override 
    public void run() { 
     while(!out) { /// <- here was the problem 
      if(num.intValue() == 1) { // since this condition will break out 
       main.interrupt();  // of the loop, you do not need it in the 
       break;    // while condition 
      } 

      String s = num.toString(); 
      int temp = 0; 
      for(int i = 0 ; i < s.length(); i++) { 
       int x = Integer.parseInt(s.substring(i, i+1)); 
       temp += x*x; 
      } 
      num = temp; 
     } 
    } 
} 

이며, 출력은

1 
1 
0 
DONE 
+0

음 .. 네. 내가 테스트 한 모든 숫자의 기록을 유지하기로되어 있었지만 여전히 메인 스레드가 중단되지 않는 이유를 이해할 수 없다. 그리고 나는 확실하지 않지만 join()이 java 6에 의해 추가되었고 Java 1.5에서 코드를 작성한다고 가정합니다. – user1232138

+0

그런 다음 try/catch 사이에 Thread.sleep (1000)을 사용할 수 있습니다. 내 메서드를 사용하여 스레드를 중단해야하기 때문에 예외를 무시하십시오. 그런데 join을 사용하는 것은이 시나리오에서는 유용하지 않습니다. 쓰래드가 의무를 끝내기를 기다리거나 중단 될 때까지 기다릴 것이기 때문입니다. – user1406062

+0

레코드 ** 시도 (FileInputStream 핀 = 새로운 FileInputStream (s)) **는 자바의 1.7 스타일이 아닙니다. 1.5 – user1406062

1

프로그램을 읽으면서 처음으로 메인 루프를 통해 num1으로 설정된 새 IsHappy 스레드가 분기됩니다. IsHappy.run() 메서드에서 num1이면 즉시 종료됩니다.

while(!out && num != 1) 

main는 잠을 스레드가 더 이상 실행되고 있기 때문에 다음 11을 인쇄하지 않습니다.

if(ishappy.isAlive()) { 
    ishappy.Exit(); 
    System.out.println(0); 
} else 
    System.out.println(11); 

예상하지 못했습니까? 디버거를 사용하는 법을 배워야한다고 생각합니다. 다음은 debug your program in Eclipse에 대한 유용한 자습서입니다. num 설정 7 번호는 다음 IsHappy.run() 방법은 스핀 가공 할 경우

는 위에 49 (7*7) 이상이어야한다. mainIsHappy이 아직 살아 있는지 확인하고 IsHappy.Exit()을 호출하고 0을 인쇄합니다. num 설정 21 번호는 다음 IsHappy.run() 방법은 스핀 가공 할 경우

는 위에 5 (2*2+1*1) 이상이어야한다. main 다시 Exit() 스레드와 인쇄 0. while 루프가 num == 1 경우 실행을 중지하기 때문에

11 
0 
0 

main 스레드가 중단되지 않습니다 :

그래서 나는 당신의 출력 인 것 같아요.

코드에 대한 몇 가지 다른 의견입니다.

  • 잡을 절대로 그냥 (당신의 IOException 캐치 참조) 예외를 던져 : 학자 연 것이 아니라 문제가되지 않습니다 그래서 이것은 테스트 코드가 될 수 있습니다. 적어도 이유를 설명하는 빈 catch 블록에 주석을 넣으십시오. 예외에 대해 신경 쓰지 마십시오.
  • 스레드가 계산을 수행하여 회전 중입니다. 이것은 분명히 자원을 잘 사용하지는 못합니다.
  • 입력 스트림이나 독자가 닫히지 않습니다. 항상 이것들을 다룰 때 try/finally를 사용하십시오.
  • Exit() 메서드는 소문자로 시작해야합니다. 메소드의 더 나은 이름은 stop입니다.
+0

코드에 대한 귀하의 의견에 자리하고있다 ...하지만 나는 어떤 경우에는 그것은 테스트 코드에서도 중요하다고 주장하고 싶다!1) 테스트 코드에서도 예기치 않은 오류가 발생하면 테스트에서 의미있는 대답을 원하면 OP가 신경 써야합니다. 4) 그는 >> 다른 사람들이 자신의 코드를 읽을 것으로 기대하고 있습니다. –

+0

글쎄, 나는 뉴비 (newbee)이기 때문에 예외를 두지 않았다. 나는 물건을 간단하게 유지하기를 원했다. 그리고 스레드가 계산을하는 것만으로 돌아가고있는 것은 아닙니다. 실제로 코드의 출력은 '11 11 0'이됩니다. 예, Thread 클래스의 exit() 메서드를 오버로드 할 수는 있지만 stop()을 사용하여 스레드를 종료 할 수는 없습니다. 스레드 클래스에서 final로 선언되어 더 이상 재정의 할 수 없습니다. main() 스레드가 인터럽트되지 않는 이유를 이해할 수 없습니다. 가능하면 도와주세요. – user1232138

+0

또한 디버거가 스레드의 코드를 실행하지 않아도 어떻게 다중 스레드 코드를 디버그 할 수 있는지 알려주십시오. NetBeans를 사용하고 있습니다. – user1232138

관련 문제