2011-08-30 4 views
0

저는 언젠가 자바 프로그래밍을 해왔지만 동시 프로그래밍에 익숙하지 않으므로 나와 함께 감당하십시오!자바 동시 콜렉션 검색

컬렉션 클래스 [예 : ArrayLists]의 그룹을 보유한 클래스를 개발하고 지정된 값을 찾으면 모든 컬렉션을 동시에 탐색하여 주어진 값을 찾으면 모든 스레드를 중지합니다.

나는 내 코드를 붙여 넣었고 선물이 반환 된 스레드 중 하나가 true를 반환하면 contains_multiple_collections()에서 어떻게 알 수 있는지 궁금한가요?

감사

그레이엄

public class CollectionGroup<V> extends ContainerGroup 
{ 
//... 
    public boolean contains(V value) 
    { 
     boolean containsValue = false; 
     if (mCollections.size() == 1) 
     { 
      containsValue = mCollections.get(0).contains(value); 
     } 
     else 
     { 
      containsValue = contains_multiple_collections(value); 
     } 
     return containsValue; 
    } 

    private boolean contains_multiple_collections(V value) 
    { 
     // thread pool 
     int numberProcessors = mCollections.size(); 
     ExecutorService es = Executors.newFixedThreadPool(numberProcessors); 

     for (int i=0; i<numberProcessors; i++) 
     { 
      AbstractCollection<V> collection = mCollections.get(i); 
      MyCallable callable = new MyCallable(collection,value); 
      Future<Boolean> future = es.submit(callable); 
      //... 
     } 

     return true; 
    } 

    private class MyCallable implements Callable<Boolean> 
    { 
     protected AbstractCollection<V> mCollection; 
     protected V      mValue; 

     public MyCallable(AbstractCollection<V> collection, V value) 
     { 
      mCollection = collection; 
      mValue  = value; 
     } 

     @Override 
     public Boolean call() throws Exception 
     { 
      boolean ok = mCollection.contains(mValue); 
      return ok; 
     } 
    } // class MyCallable 

} // class CollectionGroup 

답변

0

contains_multiple_collections 메서드는 검색이 완료 될 때까지 대기하지 않는 것이 문제입니다. 내가 생각할 수있는 두 가지 옵션이 있습니다. 첫 번째는 contains 메소드가 차단하지 않고 콜백/리스너 객체를 인수로 취하는 비동기 콜백 구현을 포함합니다. 두 번째는 결과가 결정될 때까지 contains 메소드를 차단하는 것입니다. 아래의 후속 접근법에 대한 샘플 구현을 간략히 설명 했으므로 테스트를 거치지 않아 조심스럽게 테스트해야합니다 ...

/* 
* contains_multiple_collections now blocks until the desired 
* value is located or all searches have completed unsuccessfully... 
*/ 
private boolean contains_multiple_collections(V value) { 
    // thread pool 
    int numberProcessors = mCollections.size(); 
    ExecutorService es = Executors.newFixedThreadPool(numberProcessors); 

    Object lock = new Object(); 
    AtomicBoolean outcome = new AtomicBoolean(false); 
    AtomicInteger remainingSearches = new AtomicInteger(mCollections.size()); 

    for (int i = 0; i < numberProcessors; i++) { 
     AbstractCollection<V> collection = mCollections.get(i); 
     es.submit(new MyRunnable(collection, value, lock, outcome, remainingSearches)); 
    } 

    /* Wait for searches to run. This thread will be notified when all searches 
    * complete without successfully locating the value or as soon as the 
    * desired value is found. 
    */ 
    synchronized (lock) { 
     while (!outcome.get() && remainingSearches.get() > 0) { 
      try { 
       lock.wait(); 
      } catch (InterruptedException ex) { 
       // do something sensible. 
      } 
     } 
     es.shutdownNow(); 
    } 

    return outcome.get(); 
} 

private class MyRunnable implements Runnable { 

    final AbstractCollection<V> mCollection; 
    final V      mValue; 
    final Object    lock; 
    final AtomicBoolean   outcome; 
    final AtomicInteger   remainingSearches; 

    public MyRunnable(AbstractCollection<V> mCollection, V mValue, 
      Object lock, AtomicBoolean outcome, AtomicInteger remainingSearches) { 
     this.mCollection = mCollection; 
     this.mValue = mValue; 
     this.lock = lock; 
     this.outcome = outcome; 
     this.remainingSearches = remainingSearches; 
    } 

    public void run() { 
     boolean ok = mCollection.contains(mValue); 
     if (ok || remainingSearches.decrementAndGet() == 0) { 
      synchronized (lock) { 
       if (ok) { 
        outcome.set(true); 
       } 

       lock.notify(); 
      } 
     } 
    } 
} 
+0

안녕하세요. 답장을 보내 주셔서 감사 드리며 필요한 코드의 윤곽을 잡으십시오. 내 코드를 붙여 넣기하고 코드 수행 방법을 알려 드리겠습니다. –

+0

코드를 구현 했으므로 잘 작동합니다. 또한 처음에는 동시 코딩을 처음 접했고 사용자의 접근 방식을 면밀히 연구했습니다. 구현을 테스트하기 위해 필자는 4 개의 List 그룹을 설정하고 각각을 1e7 Integers로 채우고 무작위로 알려진 값을 삽입했습니다. 따라서이 방법은 4 천만 개의 값을 통해 단일 값을 검색해야합니다. 그것은 잘 작동하고 빠릅니다. –

2

는 다른 스레드의 값을 발견 할 수 있기 때문에 단지 멈추지 않을 것입니다 포함되어 있습니다. 이렇게하는 유일한 방법은 자신을 반복하는 것입니다.

CPU 집중 프로세스의 경우 최적의 스레드 수는 보유한 코어 수입니다. 스레드를 너무 많이 생성하면 오버 헤드가 추가되어 솔루션 속도가 느려집니다.

ExecutorService를 종료 한 후에는 반드시 shutdown()을 수행해야합니다.

검색 속도를 높이려면 모든 값 집합을 유지해야합니다.이 값은 여러 스레드를 사용하는 것보다 10-100 배 빠릅니다.

+0

안녕하십니까. 내 기본 생성자는 프로세서 수에 따라 스레드 수를 만듭니다. public CollectionGroup() { super(); int numberProcessors = Runtime.getRuntime(). availableProcessors(); mCollections = new ArrayList >(); for (int i = 0; i ()); } } –

+0

목록 대신 세트 사용 방법은 어떻습니까?한 스레드의 집합은 다중 스레드 된 목록보다 빠릅니다. –

+0

안녕하세요. 감사. My ContainerGroup은 CollectionGroup, MapGroup 등의 하위 클래스의 계층 구조이며 contains(), sort() 등의 일반적인 메서드를 정의합니다. 모든 클래스에 대해. 따라서 contains()는리스트와 세트, 맵에 정의되어 집합과 함께 더 빠르다는 것을 인정합니다. –

0

모든 미래를 반복적으로 반복하여 0 또는 거의 제로를 사용하여 get으로 폴링 할 수 있지만, 더 나은 아이디어는 모든 MyCallable에 콜백을 제공하는 것입니다. 그러면 일치 항목이있을 때이를 호출해야합니다. 녹이다. 그런 다음 콜백은 ExecutorService을 종료하여 다른 모든 작업을 취소해야합니다.

1

ExecutorCompletionService를 사용할 수 있습니다. 완료된 Future가 존재할 때까지 take() 블록 (take() 블록)을 유지하고 결과를 얻고 무언가를 찾으면 기본 ExecturService를 shutdownNow()하십시오. 값을 찾으면 즉시 모든 스레드를 중지하지는 않습니다.

0

일치 항목을 찾을 때 설정되는 정적 AtomicBoolean을 사용하는 것이 좋습니다. 계속 진행하기 전에 각 스레드는 값을 확인할 수 있습니다.