2014-12-12 2 views
1

메인 C# 및 Java에서 개발하기 시작했다. 나는 스레드 :(나는 무시 run() 메소드에서 브레이크 포인트를 설정 한, 아무것도이 방법 내에서 실행 것 같다(자바) 스레드가 실행되지 않습니다

public class GetLocationInfo implements Runnable{ 

String address; 
double latitude; 
double longitude; 

public void run() { 
    HttpGet httpGet = new HttpGet("http://maps.google.com/maps/api/geocode/json?latlng=42.993504,-79.239167&sensor=false"); 
    //HttpGet httpGet = new HttpGet("http://maps.google.com/maps/api/geocode/json?latlng="+latitude+","+longitude+"&sensor=false"); 
    HttpClient client = new DefaultHttpClient(); 
    HttpResponse response; 


    try { 
     response = client.execute(httpGet); 
     HttpEntity entity = response.getEntity(); 
     InputStream stream = entity.getContent(); 

     JsonReader reader = new JsonReader(new InputStreamReader(stream, "UTF-8")); 

     reader.beginObject(); 
     while (reader.hasNext()) { 
      String name = reader.nextName(); 
      if (name.equals("formatted_address")) { 
       address = reader.nextString(); 
      } else 
       reader.skipValue(); 
     } 
     reader.endObject(); 
    } catch (ClientProtocolException e) { 
    } catch (IOException e) { 
    } 
} 


public String GetAddress(double lat, double lng) { 

    latitude = lat; 
    longitude = lng; 

    Thread thread = new Thread(this); 

    thread.start(); 
    return address; 
} 
} 

를 시작하는 데 문제가 있어요. 너희들이 내가 그것을이 똑 바르게 도울 수있는 경우 많이 주시면 감사하겠습니다.

건배

+3

캐치 블록을 비워 두었습니다. 각 catch 블록에'e.printStackTrace();'를 추가하고 예외가 던져 졌는지 확인하십시오. – Blackbelt

+3

방금 ​​스레드를 시작했습니다. 이미'주소 '가 채워질 것이라고 어떻게 생각하십니까? – njzk2

답변

0

을 나는 당신이 (당신이 미래의 결과를 얻을하고자하는 경우) 실행 가능한 또는 호출 구현하는 클래스의 '핵심 활동'을 캡슐화하는 것이 좋습니다 것입니다. 작업을 제출 ThreadpoolExecutors를 사용합니다.

0

고마워를 사용합니다. 코딩 방법이 모범 사례는 아니지만 해결 방법을 찾았습니다.

클래스의 생성자를 생성하고 거기에서 스레드를 시작하고 문자열 변수 주소를 public으로 설정했습니다.

public class GetLocationInfo implements Runnable{ 

public String address; 
double latitude; 
double longitude; 

public GetLocationInfo(double lat, double lng) { 

    latitude = lat; 
    longitude = lng; 

    Thread thread = new Thread(this); 

    thread.start(); 

} 

public void run() { 
    HttpGet httpGet = new HttpGet("http://maps.google.com/maps/api/geocode/json?latlng=42.993504,-79.239167&sensor=false"); 
    //HttpGet httpGet = new HttpGet("http://maps.google.com/maps/api/geocode/json?latlng="+latitude+","+longitude+"&sensor=false"); 
    HttpClient client = new DefaultHttpClient(); 
    HttpResponse response; 


    try { 
     response = client.execute(httpGet); 
     HttpEntity entity = response.getEntity(); 
     InputStream stream = entity.getContent(); 

     JsonReader reader = new JsonReader(new InputStreamReader(stream, "UTF-8")); 

     reader.beginObject(); 
     while (reader.hasNext()) { 
      String name = reader.nextName(); 
      if (name.equals("formatted_address")) { 
       address = reader.nextString(); 
      } else 
       reader.skipValue(); 
     } 
     reader.endObject(); 
    } catch (ClientProtocolException e) { 
    } catch (IOException e) { 
    } 
} 

}

+0

이것이 원하는 방식으로 작동하지 않는 데는 여러 가지 이유가 있습니다. 첫째, 주소를 사용하는 다른 스레드는 채워진 시점을 어떻게 알 수 있습니까? 당신은 루프를 돌릴 것입니까 (cpu 낭비)? 'FutureTask'클래스는이 시나리오 (https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/FutureTask.html) 용으로 작성되었습니다. 스레드가 완료 될 때까지 'get'을 호출하면 대기합니다. 이것을하지 않으려면 적어도 주소 필드를 '휘발성 (volatile)'으로 만들어야합니다. 그렇지 않은 경우, java는 다른 thread가 그 값을 볼 수있을 것이라고 보장하지 않습니다. – user384842

1

당신은 주 스레드가 어떻게 든 중단하고 반환하기 전에 run() 방법을 실행하기 위해 새로 만든 스레드를 기다릴 것입니다 가정하여 스레드에 대한 몇 가지 중요한 사항을 누락되었습니다.
스레드로 작업 할 때주의 사항 : 당신의 GetAddress() 방법 스레드를 시작하면

  1. 은 그것이 즉시 방법을 실행있어 전화를 그냥 계산 된 주소 때 반환에 진행됩니다 의미하지 않는다 새 스레드를 만들지 않고 run 메소드를 호출 한 것처럼 돌아옵니다. 원하는 경우 다른 스레드가 필요하지 않습니다. 두 번째 스레드를 시작하면 기본적으로 운영 체제에 새로운 스레드를 실행할 준비가되었음을 알리며 OS에 따라 스레드의 코드가 실제로 시작될시기를 정확하게 결정합니다. 다중 CPU/코어 환경에서도 정확한 지점에서 코어를 사용할 수 있다고 가정 할 수는 없습니다.
  2. 주 스레드가 다른 스레드를 시작했기 때문에 주 스레드가 실행을 중지하거나 일시 중지한다고 가정 할 수도 없습니다. 주 스레드는 결국 모든 스레드를 병렬로 실행하기에 충분한 코어가 시스템에없는 경우에만 다른 스레드가 실행되도록 잠시 동안 실행을 중지 할 수 있습니다. 어쨌든 언제 일어날 지 예측할 수 없습니다. 즉, 새 스레드를 시작한 후에 새로 작성된 스레드가 완료되거나 심지어 run() 메소드를 시작하기 전에 GetAddress() 메소드가 주소 변수의 현재 값을 호출자로 리턴 할 가능성이 훨씬 더 높습니다.
    당신이 모르는 경우 그 진실되고, 스레드를 시작한 후 다음 줄을 삽입하십시오 :

    thread.start(); 
    try {    // Used just for demonstration purposes 
        thread.join(); // This block kills the parallelism of the second thread 
    } 
    return address; 
    

이 코드는 실행하기 위해 새로 만든 스레드를 기다리는 메인 스레드를 강제로.그러나이 코드는 새 스레드를 만들면 얻을 수있는 이점을 망칠 수 있습니다.

이제 무엇을 할 수 있습니까?

여러 스레드를 처리 할 수있는 여러 가지 방법이 있지만 프로젝트에 대해 더 많이 알지 못하면 무엇이 가장 좋은 방법인지 말할 수 없습니다. 아주 간단한 예를 통해 몇 가지 방향을 제시 할 수 있습니다.
UI가있는 프로그램, 주소를 가져올 버튼 및 주소를 쓸 텍스트 필드가 있다고 가정 해 보겠습니다. 누군가가 버튼을 클릭하면 한 번에 주소를 계산하는 대신 startRetrievingAddress()과 같은 메서드를 호출하여 작업자 스레드를 시작하고 텍스트 필드에 "please wait..."과 같은 임시 텍스트를 채 웁니다. 작업 스레드의 run() 메서드 끝에 텍스트 필드를 채우기 위해 코드를 추가하여 최종 결과를 얻을 수 있습니다.
더 나은 방법은 실행 메소드가 주소 계산을 완료 할 때 알림을받는 "completition"리스너를 지원하는 작업 스레드 클래스를 만들어서 결과를 즉시 처리 할 수 ​​있도록하는 것입니다. 그들은 계산됩니다. 그런 다음 계산 된 값으로 텍스트 필드를 설정할 청취자를 등록합니다. 물론 루퍼 스레드를 사용하여 작업자 스레드에서 발행 된 메시지를 처리하는 더 나은 방법이 있지만 모든 것을 여기에서 언급 할 수는 없습니다. 행운을 빕니다!

관련 문제