如何将对象存储在内存中,并在经过Max(amount,time)

我的Spring Boot应用程序获得了输入Student,需要将其写入数据库。

我可以在获得Student对象之后立即向数据库写入数据,但是我想通过在内存中累积几个学生然后将大量Students保存到数据库中来提高效率。

因此,我正在寻找一种解决方案,该解决方案可以为Max(some duration,number of students)缓存学生,并且一旦达到限制就可以批量保存学生。

可以使用Thread这样的代码编写代码,但是看来这个问题以前可能已经解决了。

caffeineguava库,但我仍然找不到我想要的东西。

okletsgo 回答:如何将对象存储在内存中,并在经过Max(amount,time)

通常的想法是让队列中有等待刷新的对象。 刷新将由2个事件触发:按计划(超出某些持续时间)和按大小(超出队列大小)。

在纯Java中,可以使用Executors.newSingleThreadScheduledExecutor()来实现:

public abstract class FlushingCache<T> {

  private final Duration maxDuration;
  private final int maxSize;
  private final List<T> queue = new ArrayList<>();
  private final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();

  public FlushingCache(Duration maxDuration,int maxSize) {
    this.maxDuration = maxDuration;
    this.maxSize = maxSize;
    executor.scheduleWithFixedDelay(this::doFlush,maxDuration.getSeconds(),TimeUnit.SECONDS);
  }

  public synchronized void enqueue(T element) {
    println("Enqueueing element " + element);
    queue.add(element);
    if (queue.size() >= maxSize) {
      doFlush();
    }
  }

  private synchronized void doFlush() {
    List<T> batch = new ArrayList<>(queue);
    println("Flushing batch " + batch);
    flush(batch);
    queue.clear();
  }

  // The login of flushing to DB will be implemented in the sub-classes
  protected abstract void flush(List<T> batch);
}

具有以下测试数据

public static void main(String[] args) {
  FlushingCache<String> studentsCache = new FlushingCache<>(Duration.ofSeconds(10),3) {
    @Override
    protected void flush(List<String> batch) {
      println("### FLUSH TO DB " + batch);
    }
  };

  studentsCache.enqueue("1");
  studentsCache.enqueue("2");
  studentsCache.enqueue("3");

  studentsCache.enqueue("4");
}

private static void println(String message) {
  System.out.println(LocalTime.now().withNano(0).toString() + ": " + message);
}

结果是

16:07:17: Enqueueing element 1
16:07:17: Enqueueing element 2
16:07:17: Enqueueing element 3
16:07:17: Flushing batch [1,2,3]
16:07:17: ### FLUSH TO DB [1,3]
16:07:17: Enqueueing element 4
16:07:27: Flushing batch [4]
16:07:27: ### FLUSH TO DB [4]

当大小达到3时或每10秒将队列刷新到DB。

在Spring Boot应用程序中,您可以使用ScheduledExecutorService代替@Scheduled

通过@EnableScheduling启用计划

@Component
public class StudentFlushingCache {

  private final List<T> queue = new ArrayList<>();

  @Value("${student.flushing-cache.max-size}")
  private final int maxSize;

  @Scheduled(
      fixedDelayString = "${student.flushing-cache.fixed-delay}",initialDelayString = "${student.flushing-cache.initial-delay}")
  public void flushPeriodically() {
     doFlush();
  }

  public synchronized void enqueue(T element) {
    /* ... */
  }

  private synchronized void doFlush() {
    /* ... */
  }
}
,

您可以尝试以下操作: 1.创建单例班来容纳学生

public enum MyCache {
INSTANCE(new HashMap<>());

private Map<String,Student> students;

private MyCache(Map<String,Student> students) {
    this.students = students;
}...getter,setter}
  1. 创建StudentService,并添加将新Student推送到缓存中的方法:MyCache.INSTANCE.getStudents().push(...)

  2. 创建计划的服务以保留缓存:

    @配置 @EnableScheduling 公共类ScheduledService {

    @计划的(fixedDelay = 60 * 60 * 1000) 公共无效ScheduledTask(){     1.获取缓存     2.检查是否达到限制(学生人数)     3.坚持学生-studentRepository.saveAll(students)     4.空缓存-list.clear() } }

本文链接:https://www.f2er.com/3073130.html

大家都在问