我们希望将一定数量的用户请求存储到队列中,当它达到一定数量时,比如20个,或者经过了一定的时间,它会自动在java中执行一批处理。
批处理操作,如批量插入到MySQL数据库中,以避免每次请求都插入一次。
发布于 2015-08-07 16:14:05
我会将该功能封装在一个类BatchCollector中。BatchCollector将接受请求并将其存储在私有队列中。在接受请求时,它将检查队列大小并存储请求或将所有请求刷新到数据库。同步BatchCollector的公共方法,添加flush和close方法(实现AutoCloseable)。类似于BufferedOutputStream的结构。
下面是一个简单的例子。示例中使用了"synchronized",您可以将其替换为ReentrantLock (参见synchronized-vs-reentrantlock-on-performance)。也许更重要的是批处理的并发执行。这可以在batchHandler中完成,使用线程安全的批处理队列提供单独的批处理执行线程。
public final class BatchCollector<R> implements Consumer<R>, AutoCloseable {
private final Queue<R> queue = new LinkedList<>();
private final int capacity;
private final Consumer<List<R>> batchHandler;
private boolean closed;
public BatchCollector(Consumer<List<R>> batchHandler, int capacity) {
this.batchHandler = batchHandler;
this.capacity = capacity;
}
@Override
public synchronized void accept(R request) {
if (closed) throw new IllegalStateException("Closed.");
queue.add(request);
if (queue.size() == capacity) flush();
}
public synchronized void flush() {
if (closed) throw new IllegalStateException("Closed.");
List<R> batch = new ArrayList<>(queue);
queue.clear();
batchHandler.accept(batch);
}
@Override
public synchronized void close() throws Exception {
if(!closed) flush();
closed = true;
}
}发布于 2015-08-07 16:32:13
考虑一下我刚刚编写的这些接口。首先,实现这个来接受用户请求:
public interface BatchCollector {
public void accept(UserRequest request);
public void setBatchExecutor(BatchExecutor exec);
}然后是这个,以指定批处理:
public interface BatchExecutor {
public void execute(List<UserRequest> requests);
}实现类将整齐地封装接受请求和触发一批请求的执行所需的所有逻辑。何时触发执行将由BatchCollector决定,如何执行将由BatchExecutor决定
https://stackoverflow.com/questions/31872210
复制相似问题