2017-01-21 4 views
2

add 메서드를 호출하여 여러 스레드에서 구아바 캐시를 채울 예정입니다. 이제 매 30 초마다 실행되는 백그라운드 스레드에서 캐시에있는 모든 내용을 원자화 방식으로 sendToDB 메서드로 보내려고합니다.Guava 캐시를 다른 방법으로 보내는 동안 30 초마다 비우는 방법?

public class Example { 
    private final ScheduledExecutorService executorService = Executors 
     .newSingleThreadScheduledExecutor(); 
    private final Cache<Integer, List<Process>> cache = CacheBuilder.newBuilder().maximumSize(100000) 
     .removalListener(RemovalListeners.asynchronous(new CustomRemovalListener(), executorService)) 
     .build(); 

    private static class Holder { 
    private static final Example INSTANCE = new Example(); 
    } 

    public static Example getInstance() { 
    return Holder.INSTANCE; 
    } 

    private Example() { 
    executorService.scheduleAtFixedRate(new Runnable() { 
     @Override 
     public void run() { 
     // is this the right way to send cache map? 
     sendToDB(cache.asMap()); 
     } 
    }, 0, 30, SECONDS); 
    } 

    // this method will be called from multiple threads 
    public void add(final int id, final Process process) { 
    // add id and process into cache 
    } 

    // this will only be called from single background thread 
    private void sendToDB(ConcurrentMap<Integer, List<Process>> holder) { 
    // use holder here 

    } 
} 

이 내 sendToDB 방법에 cache지도를 보낼 수있는 올바른 방법인가 : 다음

내 코드? 기본적으로 30 초 동안 캐시에있는 모든 항목을 보내고 캐시를 비우려고합니다. 그 후 내 캐시는 다음 30 초 내에 다시 채워질 것입니다. 그런 다음 동일한 프로세스를 수행합니까?

나는 방법으로 캐시에서 일어나는 모든 변경 사항을 반영하므로 캐시를 비우지 않으므로 cache.asMap()이 올바른 방법이 아닐 수도 있다고 생각하십니까?

+0

'asMap'은 기억이 잘 나면 내용의 복사본을 반환하고, 1/asMap 만 복사하면 메서드 –

+0

@RC를 호출합니다. 아니, 그냥보기에요. – shmosel

+0

'add()'메소드 (적어도 개요)를 채울 수 있습니까? Java 8을 사용하고 있습니까? 지도를 삭제해야합니까, 아니면 열쇠를 남겨두고 값을 재설정 할 수 있습니까? – shmosel

답변

0

방법에 대해 :

@Override 
public void run() { 
    ImmutableMap<Integer, List<Process>> snapshot = ImmutableMap.copyOf(cache.asMap()); 
    cache.invalidateAll(); 
    sendToDB(snapshot); 
} 

이 특정 시점에서 캐시의 스냅 샷을 생성, 새로운 맵으로 캐시의 내용을 복사합니다. 그런 다음 .invalidateAll()은 캐시를 비우고 스냅 샷이 DB로 전송됩니다.

이 접근법의 한 가지 단점은 스냅 샷을 만든 후 캐시에 항목을 추가 할 수 있지만 .invalidateAll()이 호출되기 전에는 해당 항목이 데이터베이스로 전송되지 않을 수 있다는 점입니다. 캐시가 maximumSize() 설정으로 인해 항목을 제거 할 수 있으므로 걱정하지 않아도된다고 가정하지만 스냅 샷을 구성하는 동안 항목을 제거하려는 경우 다음과 같은 모양이됩니다.

cachesendToDB()이 호출 될 때 실제로는 이 아니지만 스냅 샷이 시작되기 전에 있던 모든 항목이 제거되어 데이터베이스로 전송됩니다.

또는 Cache 필드가있는 래퍼 클래스를 만들고 새 비어있는 캐시에 대한 필드를 원자 적으로 바꾼 다음 이전 캐시의 내용을 데이터베이스에 복사하고 GCed 할 수 있습니다.