2013-05-01 2 views
0

이 앱에서 온라인에서 오디오 등의 콘텐츠를 캐싱하고 있습니다. 앱의 특정 지점에서 사용자가 곧 필요할 것으로 예측하는 콘텐츠에 배치 다운로드를 실행합니다. 이 모든 것은 내 캐시 시스템과 백그라운드 스레드를 통해 수행됩니다. 그것의 기본 jist는 캐시에 url을 보내고 파일 이름에 해시 한 다음 파일의 올바른 위치를 검색합니다. 발견 된 파일의 위치를 ​​반환합니다. 그렇지 않은 경우 다운로드합니다. 파일을 찾은 다음 파일 위치를 반환합니다. 배치 작업을 수행 할 때 대기열에 던져서 스레드 풀을 막히지 않고 더 높은 우선 순위의 비동기 작업을 수행하는 것을 불가능하게 만듭니다. 이 방법은 큐가 하나의 새로운 비동기 작업을 수행 할 때 이전 작업이 완료되면 장치가 여러 작업을 실행할 수 없으면 지금 수행해야 할 작업이 다음 줄에 배치됩니다.캐싱 및 스레딩 문제

여기에 문제가 있습니다.

현재 특정 오디오 파일을 SD 카드에 쓰고 있는데 큐가 실행 중일 때 요청하면 어떻게됩니까? 두 개의 스레드가 같은 파일을 한 번에 쓸 수 있습니까?

또는 파일을 찾아 반쯤 생성되고 손상된 파일을 반환합니까?

어떻게해야합니까?

나는 우선 순위 대기열을 통해 모든 것을 실행할 가능성이 있지만, 여러 개의 비동기 스레드를 실행할 수있는 장치를 사용하면 훨씬 더 좁은 병 목을 만들 수 있습니다.

편집 : 보인다 스레드 Running multiple AsyncTasks at the same time -- not possible?

에 따라

내 응용 프로그램이 포함 안드로이드 2.3 현재

그 (모든 작업이 병렬로 실행 할 수있는 OS/디바이스 버전에 따라 한 번에 한도) 또는 한 번에 하나씩.

xD 그래서 내가 직접 관리하려고합니다.

답변

1

ConcurrentHashMap을 사용하면 동일한 파일에 여러 스레드 쓰기 문제를 피할 수 있습니다.

ConcurrentHashMap<String, Boolean> map = new ConcurrentHashMap<>(); 

public void writeToFile(String fileName, byte[] data) { 
    // putIfAbsent returns the value previously associated with fileName, or null 
    if(map.putIfAbsent(fileName, Boolean.TRUE) == null) { 
     try(FileOutputStream stream = new FileOutputStream(fileName)){ 
      stream.write(data); 
     } finally { 
      map.remove(filename); 
     } 
    } 
} 

는 너무 오래 모든 스레드가 putIfAbsent 가드를 사용,이 같은 파일 이름에 쓰는 여러 스레드를 방지 할 수 있습니다.

1

운영 체제에 따라 동일한 파일에 동시에 쓸 수도 있지만 예를 들어 Windows에서는 2 개의 프로세스가 동일한 파일을 잠글 수 없습니다. 그러나 동시에 작성하는 것은 당신이 작성한 내용이 유용한 순서로 작성된다는 것을 보증하지 않으며, 파일을 거의 확실하게 손상시킵니다.

아마도 가장 좋은 방법은 언급 한 기기의 중앙 기록기를 사용하는 것입니다. 그렇지 않으면 여러 작성자가 다른 사람이 끝내기를 기다리는 잠금 방식을 사용할 수 있습니다.