Guava Cache - быстро вернуть начальное значение и выполнить асинхронное обновление - PullRequest
0 голосов
/ 19 декабря 2018

Я пытаюсь реализовать поведение «обогащения записи в кэше»:

  1. Когда ключ является новым / устаревшим для кэша, возвращает быстро предварительно рассчитанное значение и запускает асинхронный пересчет для ключа
  2. Как только асинхронный пересчет будет выполнен, верните обновленное значение

В следующем коде это реализовано, но, очевидно, это крайне плохо.Есть ли способ добиться этого с помощью конфигурации чистого кэша?

Код + Тест:

import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListenableFutureTask;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import lombok.SneakyThrows;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.runners.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class GuavaCacheTest {

    final LoadingCache<Long, String> myCache = CacheBuilder.newBuilder()
            .maximumSize(1000)
            .build(
                    new CacheLoader<Long, String>() {

                        ExecutorService executor = Executors.newFixedThreadPool(10);

                        public String load(Long key) {
                            System.out.println("load() " + key);
                            return "INITIAL";
                        }

                        public ListenableFuture<String> reload(final Long key, String prevString) {
                            // asynchronous!
                            ListenableFutureTask<String> task = ListenableFutureTask.create(() -> {
                                System.out.println("reload() started for ... " + key);

                                try {
                                    Thread.sleep(1000);
                                } catch (InterruptedException e) {
                                    e.printStackTrace();
                                }

                                System.out.println("reload() ended for ... " + key);

                                return "Calculated value for " + key;

                            });
                            executor.execute(task);
                            return task;
                        }

                    });


    public String myget(Long key) {
        String v = myCache.getUnchecked(key);

        if (v == "INITIAL") {
            myCache.refresh(key);
            myCache.getUnchecked(key);

            v = "Initial value for " + key;
        }

        return v;
    }

    @Test
    @SneakyThrows
    public void testRepeatedCalls() {


        System.out.println("Call result: " + myget(55L));
        System.out.println("Call result: " + myget(55L));
        System.out.println("Call result: " + myget(55L));
        System.out.println("Call result: " + myget(55L));

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("---------------");

        System.out.println("Call result: " + myget(55L));
        System.out.println("Call result: " + myget(55L));
        System.out.println("Call result: " + myget(55L));
        System.out.println("Call result: " + myget(55L));

    }

}

Вывод:

load() 55
reload() started for ... 55
Call result: Initial value for 55
Call result: Initial value for 55
Call result: Initial value for 55
Call result: Initial value for 55
reload() ended for ... 55
---------------
Call result: Calculated value for 55
Call result: Calculated value for 55
Call result: Calculated value for 55
Call result: Calculated value for 55
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...