0 0

JAVA怎样做一个缓存到一定量数据后批量转移到其他地方,避免缓存太大至内存溢出?15

我想实现一个缓存队列,并发情况下向该队列写入,当达到一定量后,缓存中转移一部分数据到数据库中,同时也有多条线程在消费该缓存队列,类是一个生产者-消费者,生产能力远大于消费能力,求各位给个思路。

下面是我的一段代码,运行起来不报错,但是达不到我要的效果,也请各位看看,指点下问题。
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,感觉那种思路在并发情况下不适用啊。
还有其他办法吗?
2011年12月17日 13:29

2个答案 按时间排序 按投票排序

0 0

你在ensureCapacity上加锁嘛,这样就没线程安全了sychronized.每个对象都只有一把锁,不会有线程问题的,你的其他add和remove或者save的操作全部都加锁

2011年12月18日 20:42
0 0

去看看ArrayList的源码,里面有个ensureCapasity,你可以模仿,如果queue的长度要超过你的最大长度,你可以把老的一部分copy到你的数据库queue里面去。
记住你的这个类里面的方法要加锁,这样保证线程方面的安全~!

2011年12月17日 15:51

相关推荐

    phpExcel导出大量数据出现内存溢出错误的解决方法

    在处理大数据量的Excel文件时,使用phpExcel工具进行数据导出是一个常见的任务。然而,在这个过程中,开发者经常面临内存溢出错误的问题。这主要是因为phpExcel在内存中保存单元格信息,当数据量大时,内存消耗超过...

    java csv大数据量导出(千万级别,不会内存溢出)

    在Java开发中,处理大数据量的数据导出是一个常见的挑战,特别是在CSV格式的文件处理上。CSV(Comma Separated Values)是一种广泛使用的数据交换格式,因其简单性和通用性而受到青睐。然而,当数据量达到千万级别时...

    分页缓存

    在IT行业中,分页缓存是一种优化大数据量查询性能的技术,尤其在Web应用程序中非常常见。它通过将数据库查询结果存储在内存缓存中,减少对数据库的直接访问,从而提高系统响应速度和用户体验。本篇文章将深入探讨...

    如何避免JDBC引起的内存溢出情况

    - **使用流式处理**:如果可能的话,使用流式处理的方式来处理结果集,这样可以避免一次性将所有数据加载到内存中。 - **限制查询结果**:尽可能地使用LIMIT或TOP等关键字来限制查询返回的行数。 #### 四、结论 在...

    统计缓存(java对象所占的内存)大小

    1. **Java VisualVM**:这是一个强大的Java性能分析工具,可以显示对象的大小、内存分配和垃圾回收情况。通过“对象”视图,可以观察到对象实例的大小。 2. **JOL (Java Object Layout)**:JOL是一个轻量级库,它...

    java map 实现缓存技术

    在Java编程中,Map接口是数据结构中非常重要的一个部分,它提供了键值对的存储方式,便于快速访问和操作数据。在许多实际应用中,尤其是高性能和高并发的场景,Map常被用来实现缓存技术,以提高数据读取速度和系统...

    java缓存数据

    - **缓存粒度**:确定合适的数据粒度,避免因缓存过大的对象导致内存浪费,或因缓存过小的对象而频繁更新。 - **缓存失效**:合理设置缓存过期策略,如TTL(Time To Live)和TTI(Time To Idle),防止数据过期未...

    Java_批量导出大数据量Excel方法.zip

    在Java开发中,批量导出大数据量到...通过以上方法,开发者可以构建一个高效且健壮的Java批量导出大数据量到Excel的解决方案。具体实现细节可能在提供的excelproj和ExpXLS文件中有所体现,建议解压后仔细研究源代码。

    完美解决TensorFlow和Keras大数据量内存溢出的问题

    内存溢出问题是参加kaggle比赛或者做大数据量实验的第一个拦路虎。 以前做的练手小项目导致新手产生一个惯性思维——读取训练集图片的时候把所有图读到内存中,然后分批训练。 其实这是有问题的,很容易导致OOM。...

    android 轻松避免内存溢出

    本项目提供了一个在Android 1.6 SDK环境下编写的工具类,旨在帮助开发者有效地避免内存溢出,特别是在加载图片列表时。以下是关于这个主题的详细讲解。 1. **Android内存机制**: - Android系统为每个应用程序分配...

    java 数据缓存

    尤其是在Java开发中,数据缓存被广泛应用于处理频繁访问的数据,避免每次请求都直接与数据库交互,从而减少I/O操作,降低系统负载。本文将深入探讨Java中的数据缓存,结合给定的标签"源码"和"工具",我们将从源码...

    JAVA的缓存应用介绍

    JAVA的缓存应用主要涉及到Java内存体系的理解、基础缓存的使用、缓存框架的介绍以及内存溢出状况的分析和内存检查工具的使用。在深入探讨这些话题之前,我们首先需要了解Java内存体系的基本概念。 Java内存体系主要...

    android异步加载网络图片,双缓存内存加sd卡缓存 绝对不会出现内存溢出oom

    本文将深入探讨如何实现一个高效、安全的网络图片加载机制,结合双缓存策略,确保图片加载过程既快速又不会导致内存溢出(Out Of Memory, OOM)。 首先,我们要理解为什么需要异步加载。在Android中,如果在主线程...

    内存溢出解决

    - **合理使用缓存**:对于需要缓存的对象,要考虑到其生命周期,避免无限增长导致内存溢出。 ##### 6. **使用合适的垃圾回收器** 选择合适的垃圾回收器对提高应用性能同样重要。例如: - **Serial GC**:适合单核...

    J2Cache 基于内存和 Redis 的两级 Java 缓存框架

    第一级缓存使用内存(同时支持 Ehcache 2.x、Ehcache 3.x 和 Caffeine),第二级缓存使用 Redis(推荐)/Memcached 。 由于大量的缓存读取会导致 L2 的网络成为整个系统的瓶颈,因此 L1 的目标是降低对 L2 的读取次数。 ...

    仿redis缓存Java版轻量级缓存组件LocalCache

    仿redis缓存Java版轻量级缓存组件LocalCache,基于JVM内存实现数据缓存及过期机制

    Java实现的树以及包含树的内存缓存框架

    随手写了一个TreeNode,顺道实现了个对应的内存缓存框架,适用于数据量不大,更新也少但是反复要读的数据,比如模块信息/组织结构/频道栏目/权限等。 PS:Java是可以直接操作内存的,只是现在的框架整合让人退化了。...

    Java内存溢出的详细解决方案

    Java内存溢出的详细解决方案 Java内存溢出是指Java虚拟机...Java内存溢出是一种常见的错误,需要通过设置合适的堆大小和PermGen space大小、降低对象创建速度和减少Class数量、使用垃圾回收机制和对象池或缓存来避免。

    自己实现一个内存缓存

    自己实现一个内存缓存涉及到许多关键点,包括数据结构的选择、缓存淘汰策略、线程安全以及内存管理等。下面将详细讨论这些知识点。 首先,我们要考虑数据结构的选择。在内存缓存中,最常见的数据结构是哈希表(Hash...

Global site tag (gtag.js) - Google Analytics