2010-01-17 5 views
6

스레드는 종종 Thread 클래스를 확장하거나 Runnable 클래스를 구현하여 두 가지 방법 (see java tutorials)으로 설계됩니다. 어느 쪽이든, 스레드 내에서 실행될 것을 지정해야합니다.하나의 클래스에서 여러 스레드를 다루는 방법은 무엇입니까?

나는 다양한 종류의 정보를 검색하는 온라인 리소스를 향한 어댑터 인 클래스를 디자인했다. 이 클래스는 getInformationOfTypeA() 및 getInformationOfTypeB()와 같은 메소드로 구성됩니다. 둘 다 온라인 리소스에 연결하는 코드를 포함하므로 교착 상태를 피하기 위해 두 가지 모두 스레드되어야합니다.

질문은 : 어떻게 설계해야합니까? 나는 아래처럼 할 수있다, 그러나 나는 단지 하나의 방법 구현할 수 : 각 방법에 대해 별도의 클래스를 만들어 것이다

public class OnlineResourceAdapter implements Runnable { 

    public void run() { 
     //get stuff from resource 
     getInformationOfTypeA(); 
    } 

    public static void main(String args[]) { 
     (new Thread(new OnlineResourceAdapter())).start(); 
    } 

    public void getInformationOfTypeA(){ 
     //get information of type A 
    } 

    public void getInformationOfTypeB(){ 
     //get information of type B 
    } 

} 

또 다른 방법은, 그러나 그것은 나에게 부 자연스럽게 보인다.

는 Btw는 : 나는 J2ME에 내 응용 프로그램을 개발하고 있어요

UPDATE :

: 답변에

덕분에 나는이 방법으로 다음과 같은 것을 사용하는 대부분의 양복지 생각

당신은 어떻게 생각하십니까 :

public class OnlineResourceAdapter{ 
    public void getInformationOfTypeA(){ 
     Thread t = new Thread(new Runnable() {   
      public void run() { 
       //do stuff here 
      } 
     }); 
     t.start(); 
    } 

    public void getInformationOfTypeB(){ 
     Thread t = new Thread(new Runnable() {   
      public void run() { 
       //do stuff here 
      } 
     }); 
     t.start(); 
    } 
} 

뭐 이거 생각해?

답변

1

각 클래스에 대해 Runnable을 기반으로 익명 클래스를 만듭니다. 이렇게하면 run() 메소드 내에서 수행해야 할 작업을 수행 할 수 있습니다.

6

Runnable을 구현해야하는 InformationOfTypeAFetcherInformationOfTypeBFetcher의 두 가지 클래스가 실제로 있어야하는 것처럼 들리겠습니다. 그들 각각은 OnlineResourceAdapter (또는 이와 유사한 것)의 인스턴스에 대한 참조를 가질 수 있지만, 다른 일을하고 있다면 다른 클래스 여야합니다. 자바는 고차 함수와 코드의 변경 부분을 지원하지 않습니다 고려, 여러 클래스를 만드는 아이디어를 좋아하지 않는 이유가 표시되지 않습니다

1

는 알고리즘이다. 당신이 OnlineResourceAdapter의 하나의 구현을 원한다면

하지만 당신은 전략 패턴을 사용하고 같은 것을 할 수있는 :

public interface InformationGetter { 
    public void getInformation(); 
} 

public class OnlineResourceAdapter implements Runnable { 
    private final InformationGetter informationGetter; 

    public OnlineResourceAdapter(InformationGetter i) { 
    this.informationGetter = i; 
    } 

    public void run() { 
     //get stuff from resource 
     i.getInformation(); 
    } 
} 

를하고 필요에 따라 다음 물론 당신은 InformationGetter의 많은 구현을 만들 것입니다.

이 접근 방식을 되돌아 보니 이제 OnlineResourceAdapter은 실제로 InformationGetter을 실행하는 것 외에는 아무 것도 추가하지 않습니다. 그래서 당신이하지 않을 강력한 이유가 없다면, 나는 InformationGetterRunnable으로 직접 구현한다고 말하고 싶습니다.

+0

danben이 내 의견을 반향합니다. 전략 패턴은 당신이 바라는 것 중 하나입니다. 분리 된 클래스를 갖는 것이이 경우에 나에게 깨끗한 방법처럼 보입니다. – Aadith

1

많은 사람들이 여러 클래스를 사용하여이를 수행하는 좋은 방법을 이미 제안했습니다.

public class OnlineResourceAdapter implements Runnable 
{ 
    private string resourceType; 

    public OnlineResourceAdapter(string resourceType) 
    { 
     this.resourceType = resourceType; 
    } 

    public void run() { 
     if (resourceType.equals("A") { 
      getInformationOfTypeA(); 
     } else { 
      // etc.. 
     } 
    } 

    public void getInformationOfTypeA(){ 
     //get information of type A 
    } 

    public void getInformationOfTypeB(){ 
     //get information of type B 
    } 
} 

사용법 :

(new Thread(new OnlineResourceAdapter("A"))).start(); 
+0

정말로 그렇게하지 않으면 정말로하지 않아야합니다. 정적 타이핑이 가능할수록 좋습니다. 다른 말로하면 두 개의 별도 클래스가 있습니다. –

+0

반면에 검색 할 수있는 정보 유형이 수천 가지이거나받는 정보 유형이 사용자가 입력하는 매개 변수 인 경우이 메서드는 형식을 constructor 매개 변수로 사용하는 것이 훨씬 더 합리적입니다 각 유형에 대해 새 클래스를 만듭니다. 포스터의 요구 사항에 대해 더 많이 알지 못하면 최상의 솔루션이 무엇인지 말할 수 없습니다. –

-1

사용하여 여러 클래스를 필요로하지 않는 방식을 선호하는 것 때문에, 당신은 또한 리소스를 가져올에 대한 정보를 제공하기 위해 생성자를 사용하여 고려할 수 있습니다 Callable 형식의 익명 클래스 (Runnable과 달리, 값을 반환 할 수 있음)는 Executor을 사용하여 실행합니다. informationA와 informationB를 검색하는 로직이 매우 비슷한 경우, 물론 리팩터링하여 단일 클래스를 사용하여 Callable의 내부 클래스를 매개 변수화 할 수 있습니다.

Callable 및 Executor가 J2ME 스펙의 일부인지 확실하지 않습니다. 표준 자바에서는 어쨌든 Proxy 접근 방식을 사용하고 외부 리소스를 인터페이스로 캡슐화합니다.

public class AsyncMethodsTest { 

    public class OnlineResourceAdapter { 

     private final ExecutorService executor = Executors.newFixedThreadPool(2); 

     public String getInformationOfTypeA() throws InterruptedException, ExecutionException, 
       TimeoutException { 
      Callable<String> callable = new Callable<String>() { 
       @Override 
       public String call() throws Exception { 
        // Connect to external resource 
        Thread.sleep(500); 
        return "A"; 
       } 

      }; 
      Future<String> submit = executor.submit(callable); 
      return submit.get(1000, TimeUnit.MILLISECONDS); 
     } 

     public String getInformationOfTypeB() throws InterruptedException, ExecutionException, 
       TimeoutException { 
      Callable<String> callable = new Callable<String>() { 
       @Override 
       public String call() throws Exception { 
        // Connect to external resource 
        Thread.sleep(1500); 
        return "B"; 
       } 

      }; 
      Future<String> submit = executor.submit(callable); 
      return submit.get(1000, TimeUnit.MILLISECONDS); 
     } 

    } 

    @Test 
    public void testMethodCalls() throws Exception { 
     OnlineResourceAdapter adapter = new OnlineResourceAdapter(); 
     assertNotNull(adapter.getInformationOfTypeA()); 
     assertNotNull(adapter.getInformationOfTypeB()); 
    } 
} 
+1

불행히도 Java ME에는'java.util.concurrent'가 없습니다. – BalusC

4

Thorbjørn Ravn Andersen과 같이 두 개의 익명 내부 클래스가 모호합니다. 다음 코드 예제는 다음과 같습니다

public class OnlineResourceAdapter { 

    public final Runnable typeA; 
    public final Runnable typeB; 

    public OnlineResourceAdapter() { 
     typeA = new Runnable() { 
      public void run() { 
       OnlineResourceAdapter.this.getInformationOfTypeA(); 
      } 
     }; 
     typeB = new Runnable() { 
      public void run() { 
       OnlineResourceAdapter.this.getInformationOfTypeB(); 
       // one can use a non-final typed variable 
       // to store, which then<1> 
      } 
     }; 
    } 

    public static void main(String args[]) { 
     OnlineResourceAdapter x = new OnlineResourceAdapter(); 
     new Thread(x.typeA).start(); // start A 
     new Thread(x.typeB).start(); // start B 
     // <1>can be accessed here. 
    } 

    public void getInformationOfTypeA(){ 
     // get information of type A 
     // return the data or directly store in OnlineResourceAdapter. 
    } 

    public void getInformationOfTypeB(){ 
     //get information of type B 
    } 

} 

편집 : 예, 당신이 제안하는 방법은 좋은 방법입니다. 메서드를 정적으로 만들 수도 있습니다. "OnlineResourceAdapter.this"를 사용할 수 있습니다. 결과를 저장하기 위해 다른 변수에 액세스 할 수 있습니다.

+0

내 버전의 익명 클래스에 대해 어떻게 생각하십니까? – hsmit

+0

제대로 작동합니다. 이 클래스가 스레딩을 처리하도록하는 것이 좋을지 확신하지 못합니다. 다른 클래스에서 제어 할 수 없기 때문입니다. 빠른 해결책으로는 효과가 있지만 장기적인 해결책으로는 조언하지 않습니다. 아마도 "getInformationOfTypeARunnable()"메소드에 의해 Runnable 인터페이스를 노출 할 것입니다. 또한 다른 스레드에서 액세스하려고 할 때 변수의 동기화 ("volatile"키워드)를 잊지 마십시오. – Pindatjuh

관련 문제