我想实现一个缓存队列,并发情况下向该队列写入,当达到一定量后,缓存中转移一部分数据到数据库中,同时也有多条线程在消费该缓存队列,类是一个生产者-消费者,生产能力远大于消费能力,求各位给个思路。
下面是我的一段代码,运行起来不报错,但是达不到我要的效果,也请各位看看,指点下问题。
package com.pb.test.queue;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.ReentrantLock;
public class MessageQueue {
private BlockingQueue<Object> queue = new LinkedBlockingQueue<Object>(10);
private BlockingQueue<Object> bufferQueue = new LinkedBlockingQueue<Object>();
// 模拟数据库
private BlockingQueue<Object> dbQueue = new LinkedBlockingQueue<Object>();
private final AtomicBoolean isQueueAdded = new AtomicBoolean(true);
private final ReentrantLock putLock = new ReentrantLock();
public void add(Object o) {
if (isQueueAdded.get()) {
if (!queue.offer(o)) {
addBuffer(o);
isQueueAdded.set(false);
}
} else {
addBuffer(o);
}
}
private void addBuffer(Object o) {
bufferQueue.offer(o);
// 模拟向数据库写入
if (bufferQueue.size() >= 20) {
List<Object> ary = new ArrayList<Object>();
bufferQueue.drainTo(ary);
for (Object i : ary) {
dbQueue.offer(i);
}
}
}
/**
* 先从queue开始消费,消费完了开始消费数据库缓存的,然后在消费bufferQueue队列中的
*
* @return
*/
public Object poll() {
Object o = queue.poll();
if (o != null) {
return o;
}
final ReentrantLock putLock = this.putLock;
putLock.lock();
try {
List<Object> ary = new ArrayList<Object>(10);
int s = dbQueue.drainTo(ary, 10);
if (s == 0) {
o = bufferQueue.poll();
if (o == null) {
isQueueAdded.set(true);
}
return o;
} else {
for (Object i : ary) {
queue.offer(i);
}
return queue.poll();
}
} finally {
putLock.unlock();
}
}
public void display() {
System.out.println(queue.size() + "\t" + bufferQueue.size() + "\t" + dbQueue.size() + "\t" + (queue.size() + bufferQueue.size() + dbQueue.size()));
}
}
问题补充:successfulroof 写道
去看看ArrayList的源码,里面有个ensureCapasity,你可以模仿,如果queue的长度要超过你的最大长度,你可以把老的一部分copy到你的数据库queue里面去。
记住你的这个类里面的方法要加锁,这样保证线程方面的安全~!
看了下ensureCapacity,感觉那种思路在并发情况下不适用啊。
还有其他办法吗?
相关推荐
在处理大数据量的Excel文件时,使用phpExcel工具进行数据导出是一个常见的任务。然而,在这个过程中,开发者经常面临内存溢出错误的问题。这主要是因为phpExcel在内存中保存单元格信息,当数据量大时,内存消耗超过...
在Java开发中,处理大数据量的数据导出是一个常见的挑战,特别是在CSV格式的文件处理上。CSV(Comma Separated Values)是一种广泛使用的数据交换格式,因其简单性和通用性而受到青睐。然而,当数据量达到千万级别时...
在IT行业中,分页缓存是一种优化大数据量查询性能的技术,尤其在Web应用程序中非常常见。它通过将数据库查询结果存储在内存缓存中,减少对数据库的直接访问,从而提高系统响应速度和用户体验。本篇文章将深入探讨...
- **使用流式处理**:如果可能的话,使用流式处理的方式来处理结果集,这样可以避免一次性将所有数据加载到内存中。 - **限制查询结果**:尽可能地使用LIMIT或TOP等关键字来限制查询返回的行数。 #### 四、结论 在...
1. **Java VisualVM**:这是一个强大的Java性能分析工具,可以显示对象的大小、内存分配和垃圾回收情况。通过“对象”视图,可以观察到对象实例的大小。 2. **JOL (Java Object Layout)**:JOL是一个轻量级库,它...
在Java编程中,Map接口是数据结构中非常重要的一个部分,它提供了键值对的存储方式,便于快速访问和操作数据。在许多实际应用中,尤其是高性能和高并发的场景,Map常被用来实现缓存技术,以提高数据读取速度和系统...
- **缓存粒度**:确定合适的数据粒度,避免因缓存过大的对象导致内存浪费,或因缓存过小的对象而频繁更新。 - **缓存失效**:合理设置缓存过期策略,如TTL(Time To Live)和TTI(Time To Idle),防止数据过期未...
在Java开发中,批量导出大数据量到...通过以上方法,开发者可以构建一个高效且健壮的Java批量导出大数据量到Excel的解决方案。具体实现细节可能在提供的excelproj和ExpXLS文件中有所体现,建议解压后仔细研究源代码。
内存溢出问题是参加kaggle比赛或者做大数据量实验的第一个拦路虎。 以前做的练手小项目导致新手产生一个惯性思维——读取训练集图片的时候把所有图读到内存中,然后分批训练。 其实这是有问题的,很容易导致OOM。...
本项目提供了一个在Android 1.6 SDK环境下编写的工具类,旨在帮助开发者有效地避免内存溢出,特别是在加载图片列表时。以下是关于这个主题的详细讲解。 1. **Android内存机制**: - Android系统为每个应用程序分配...
尤其是在Java开发中,数据缓存被广泛应用于处理频繁访问的数据,避免每次请求都直接与数据库交互,从而减少I/O操作,降低系统负载。本文将深入探讨Java中的数据缓存,结合给定的标签"源码"和"工具",我们将从源码...
JAVA的缓存应用主要涉及到Java内存体系的理解、基础缓存的使用、缓存框架的介绍以及内存溢出状况的分析和内存检查工具的使用。在深入探讨这些话题之前,我们首先需要了解Java内存体系的基本概念。 Java内存体系主要...
本文将深入探讨如何实现一个高效、安全的网络图片加载机制,结合双缓存策略,确保图片加载过程既快速又不会导致内存溢出(Out Of Memory, OOM)。 首先,我们要理解为什么需要异步加载。在Android中,如果在主线程...
- **合理使用缓存**:对于需要缓存的对象,要考虑到其生命周期,避免无限增长导致内存溢出。 ##### 6. **使用合适的垃圾回收器** 选择合适的垃圾回收器对提高应用性能同样重要。例如: - **Serial GC**:适合单核...
第一级缓存使用内存(同时支持 Ehcache 2.x、Ehcache 3.x 和 Caffeine),第二级缓存使用 Redis(推荐)/Memcached 。 由于大量的缓存读取会导致 L2 的网络成为整个系统的瓶颈,因此 L1 的目标是降低对 L2 的读取次数。 ...
仿redis缓存Java版轻量级缓存组件LocalCache,基于JVM内存实现数据缓存及过期机制
随手写了一个TreeNode,顺道实现了个对应的内存缓存框架,适用于数据量不大,更新也少但是反复要读的数据,比如模块信息/组织结构/频道栏目/权限等。 PS:Java是可以直接操作内存的,只是现在的框架整合让人退化了。...
Java内存溢出的详细解决方案 Java内存溢出是指Java虚拟机...Java内存溢出是一种常见的错误,需要通过设置合适的堆大小和PermGen space大小、降低对象创建速度和减少Class数量、使用垃圾回收机制和对象池或缓存来避免。
自己实现一个内存缓存涉及到许多关键点,包括数据结构的选择、缓存淘汰策略、线程安全以及内存管理等。下面将详细讨论这些知识点。 首先,我们要考虑数据结构的选择。在内存缓存中,最常见的数据结构是哈希表(Hash...