2017-11-07 7 views
2

이 나는 ​​상황에 붙어입니다.Java - AtomicReferenceArray를 사용해야합니까?</p> <p>새로운 객체가 설정 참조 (<code>null</code>)의 크기 <code>n</code>의 배열에 의해 인스턴스화되고 :

빌드 단계에서는 각 인덱스에 정확히 한 번만 참조를 할당 한 다음 전체 채워진 배열을 반환해야합니다.

복잡성은 배열이 여러 스레드에 의해 병렬로 공급된다는 것입니다.

두 스레드가 동일한 인덱스에 액세스 할 수 없기 때문에 집합 연산의 원 자성에 신경 쓰지 않지만 채워진 배열을 반환하는 스레드가 채워진 모든 인덱스를 "확인"하고 싶습니다.

private final String[] arr = new String[n]; 

private void parallelFeed() {...} // Multi-threaded 

public void build() { 
    parallelFeed(arr); 
    return arr; 
} 

AtomicReferenceArray을 사용해야합니까?

감사합니다 다음 당신의 도움

답변

3

parallelFeed에서 피더 스레드를 시작하십시오. 피더 스레드는 겹치지 않는 것으로 가정하고 배열을 완전히 채울 수 있도록 각 범위를 갖습니다. 그런 다음 parallelFeed에서 join 스레드. parallelFeed은 다른 theads가 완료 될 때까지 기다릴 것입니다. 아무 스레드도 작업을 수행하지 못한다고 가정하면 parallelFeed은 모든 색인이 채워 졌음을 "인식"합니다.

참고은 "스칼라 선물은"당신의 코멘트에 언급 때문에

, 오류가 발생할 수 있습니다 최대 다수의 선물 "가입"할 수있는 방법에 대한 자세한 논의 How to wait for several futures를보십시오.

+0

답장을 보내 주셔서 감사합니다. 쓰레드를 어떻게 조인해야하는지 모르겠습니다. 저는 현재 자바의 것과 비슷한 Scala의 Future API를 사용하고 있습니다. 선물이'Await.ready (Futures.sequence (future), 1.hour)'로 완성 될 때까지 기다리고 있습니다.이 작업이 스레드에 합류하면 알 수 있습니까? 당신의 도움을 주셔서 감사합니다 – ogen

+0

'futures'는'Future's의 목록 일뿐입니다, 예, 작동해야합니다 ('Futures.sequence's/b'Futex.sequence'를 수정 한 후) – Les

1

각 스레드는 인덱스의 그것의 자신의 세트를 처리하는 경우에 대한 많은 당신이 할 필요가 대기하기 위해 '채워진 배열을 반환 스레드'에서 모든 스레드에 join입니다 그들 모두가 달릴 때까지. 아니요, AtomicReferenceArray을 필요로합니다.

0

쓰기 스레드는 배열 채우기 작업을 마치면 volatile 필드에 쓸 수 있습니다. 그런 다음 return arr 직전에 volatile 필드를 읽으십시오. volatile 필드의 쓰기/읽기가 happens-before을 설정하기 때문에 어레이의 데이터를 확실하게 볼 수 있습니다.

위의 내용은 필요한 스레드간에 추가 동기화가 필요 없다는 것을 전제로합니다. 즉, 동일한 인덱스에 쓸 수 없으며, 이와 같은 방법으로도 쓸 수 없습니다.

샘플 코드 :

public class WriteReadSyncArray<E> { 

    private final E[] store; 
    private volatile boolean sync; 

    public WriteReadSyncArray(int size) { 
     this.store = (E[]) new Object[size]; 
    } 

    public void write(int index, E el) { 
     store[index] = el; 
     sync = true; 
    } 

    public E[] syncAndReadArray() { 
     boolean localSync = sync; // establishes happens-before with all previous writes 
     return store; 
    } 
} 
+0

휘발성 [배열의 색인에 할당 할 때 휘발성] (https://www.javamex.com/tutorials/volatile_arrays.shtml). – Michael

+0

@Michael의 링크 된 자원은 내가 제안한 것이 아닙니다. –

+0

그럼 당신은 무엇을 제안 했습니까? – Michael

1

만 가시성을 보장하려면, 당신은 기본적으로 후있어 무엇 volatile 키워드입니다. 불행히도 volatiledoes not work well with arrays이며 다소 문제를 해결해야합니다. 링크가 설명하는 것처럼 가능하지만 추천하지는 않습니다.

나는 이것을 Future 컬렉션으로 구현할 것이다. 각 작업은 Future<String[]>이고 "주"스레드는 모든 결과를 최종 배열로 컴파일합니다. 아래를 참조하십시오.

import java.util.ArrayList; 
import java.util.Arrays; 
import java.util.List; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
import java.util.concurrent.Future; 

public class Test 
{ 
    private String[] arr = new String[2]; 

    public Test() throws Exception // You may want to handle the exceptions more 
    {        // gracefully than this 
     final int NUM_THREADS = 10; 
     ExecutorService executor = Executors.newFixedThreadPool(NUM_THREADS); 

     // Start the tasks 
     List<Future<String[]>> tasks = new ArrayList<>(); 

     tasks.add(
      executor.submit(() -> partOne()) 
     ); 
     tasks.add(
      executor.submit(() -> partTwo()) 
     ); 

     // Compile result 
     for (Future<String[]> task : tasks) 
     { 
      final String[] result = task.get(); // This will wait if necessary 
      for (int i = 0; i < result.length; ++i) 
      { 
       if (result[i] != null) arr[i] = result[i]; 
      } 
     } 

     System.out.println(Arrays.toString(arr)); 
     executor.shutdown(); 
    } 

    private static String[] partOne() 
    { 
     String[] arr = new String[2]; 
     arr[0] = "Hello"; 
     return arr; 
    } 

    private static String[] partTwo() 
    { 
     String[] arr = new String[2]; 
     arr[1] = "World"; 
     return arr; 
    } 

    public static void main(String... args) throws Exception 
    { 
     new Test(); 
    } 
}