두 개의 스레드와 캐시가 있습니다. 스레드 1을 Tb로 부르겠습니다. 백그라운드 스레드 (즉, 낮은 우선 순위)이고 다른 스레드는 Tm (우선 순위가 더 높은 주 스레드)입니다. 두 스레드에 의해 업데이트되는 캐시가 있습니다. 스레드 Tb가 가능할 때 캐시를 선제 채우기 위해 스레드 Tb가 Tm의 보조자와 비슷하다고 말할 수 있습니다.두 스레드 간의 자원 액세스가 동기화되었습니다.
Tm이 캐시에 대한 액세스를 원할 때 UI 업데이트가 일부 표시되기 때문에 즉시 액세스해야합니다. 다음과 같이 캐시가 동시 쓰기에 공유되기 때문에
는, 나는 캐시에 대한 액세스를 동기화 한 :
Element checkAndUpdateCache(int elementPositionToBeChecked){
Element toBeReturned;
synchronized(lock){
// Check if the element is already present in the cache
if(!cache.hasElement(elementPositionToBeChecked)){
// If not, retrieve a new one and fill the cache
toBeReturned = retrieveNewElement(elementPositionToBeChecked);
cache.put(elementPositionToBeChecked, toBeReturned);
}
else{
toBeReturned = cache.getElement(elementPositionToBeChecked);
}
}
return toBeReturned;
}
문제는 백그라운드 스레드는 루프에서이 메서드를 호출하기 때문에, 아주 빨리 계속 요구한다는 것입니다 캐시에 액세스 할 수 있으며 잠금 장치를 거의 놓을 수 없습니다. 현재, 매 루프 사이클 후에 Thread.yield()를 호출하고 Thread.sleep (10)을 호출하여 주 스레드에 대한 액세스 권한을 부여합니다.
우선 순위가 다르면 매 루프 사이클마다 Thread.yield()가 도움이되지 않습니다. Thread.sleep()은 다소 도움이되지만 나는 모두 좋은 전략이 아님을 동의합니다. 결국 우리는 최대 CPU 사용률을 원할 것입니다.
주 스레드가 캐시에 액세스해야 할 때마다 백그라운드 스레드가 스레드를 기다리고 조금 후에 작업을 다시 시작하는 동안 언제든지이를 확보 할 수있는 방법이 있습니까?
편집 : 구현 세부 사항
캐시 키가 Integer
곳의 Map<Integer, Album>
입니다.
public static Album getAlbum(Context context, int position, @NonNull Cursor cursor, @NonNull Map<Integer, Album> cache){
// Do we have the Album in cache
Album albumInfo = cache.get(position);
if(albumInfo == null){
cursor.moveToPosition(position);
// Let's cache this Album
albumInfo = Album.fromMediaStoreCursor(context, cursor);
cache.put(position, albumInfo);
}
EDIT 2
return albumInfo;
}
편집 2 : 진짜 좋은 충고하지만 가능한 솔루션에 그대로 내 마음에 오는을 제공하기 어렵다 완전한 구현을 모른 채
// While we pre-emptively fetch the Albums to cache in the background :)
if (cursorImages != null) {
for (int i = 0; i < cursorImages.getCount(); i++) {
synchronized(SnapsboardApplication.getInstance()) {
AlbumsListCursorAdapter.getAlbum(ListPhotoVideoAlbumsOnDeviceActivity.this,
i, cursorImages, cache);
}
// Keep checking if we have been asked to cancel
if (isCancelled()) {
return null;
}
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
Thread.yield();
}
}
구현 된 캐시 란 무엇입니까? 'java.util.concurrent' 컬렉션을 사용한다면 당신은 전혀 동기화 할 필요가 없습니다. – EJP
'Tm'은 캐시 자체에 데이터를 추가합니까, 아니면 순전히 읽기 액세스입니까? – Lothar
@EJP : 한 스레드가 pos p에 대해 캐시가 비어있는 것을 발견하고 캐시를 채우는 동안 주 스레드가 캐시를 검사하여 pos p를 찾은 다음 비어있는 것으로 판단하지만 곧 만만치 않다. 곧 –