Android 如果锁定,缓存事件会导致崩溃
Android caching events results in crashing if locking
当 Android 应用程序不在前台时,我将事件存储在队列中。事件可能很多,所以我想在达到一定限制时删除最旧的事件以避免内存问题。事件可以是不同类型的,我想避免删除某些(如果不是真的需要,例如 onTrimMemory())。
public void enqueue(T event) {
synchronized (events) {
if (events.size() > 2000) {
for (int i = 0; i < events.size(); i++) {
if (canRemove(events.get(i))) {
events.remove(i);
break;
}
}
}
events.add(event);
}
}
canRemove(event) 检查 Event 是否是可以删除的东西的 instanceof 并且 returns true/false.
过了一会儿 Logcat 给我:"long monitor contention event with owner method" 过了一会儿 Logcat 报告
开始阻塞 GC Alloc
等待阻塞 GC 分配
将目标 GC 堆从 65MB 钳制到 64MB,然后,在收到大量不同的消息后...应用程序崩溃。
根据我阅读类似问题 (What might be the cause of "long monitor contention event with owner method"?) 的理解,问题是我正在接收大量事件并将事件锁定 "too much" 时间。
所以问题是...我能做什么?我可以通过保存我删除的最后一个位置并在下次从它开始 for 循环来优化它,但我认为这还不够。或者我可以为不同的事件做不同的队列,这样我总是删除第一个,但我总是需要锁定它。有更好的主意吗?
我忘了说我要声明:private LinkedList events = new LinkedList<>();
使用这个方法
public void enqueue(T event) {
List<T> removable = new ArrayList<>();
synchronized (events) {
final int size = events.size();
if (size > 2000) {
for (int i = 0; i < size; i++) {
final T t = events.get(i);
if (canRemove(t)) {
removable.add(t);
break;
}
}
}
if (removable.size() > 0) {
events.removeAll(removable);
}
events.add(event);
}
}
希望它能解决您的问题。
我认为您可以使用 events.subList
方法来代替删除对象,如下所示:
public void enqueue(T event) {
List<T> removable = new ArrayList<>();
synchronized (events) {
final int size = events.size();
if (size > 2000) {
int removeSize = events.size() - 2000;
events = events.subList(removeSize, events.size());
}
events.add(event);
}
}
当 Android 应用程序不在前台时,我将事件存储在队列中。事件可能很多,所以我想在达到一定限制时删除最旧的事件以避免内存问题。事件可以是不同类型的,我想避免删除某些(如果不是真的需要,例如 onTrimMemory())。
public void enqueue(T event) {
synchronized (events) {
if (events.size() > 2000) {
for (int i = 0; i < events.size(); i++) {
if (canRemove(events.get(i))) {
events.remove(i);
break;
}
}
}
events.add(event);
}
}
canRemove(event) 检查 Event 是否是可以删除的东西的 instanceof 并且 returns true/false.
过了一会儿 Logcat 给我:"long monitor contention event with owner method" 过了一会儿 Logcat 报告
开始阻塞 GC Alloc
等待阻塞 GC 分配
将目标 GC 堆从 65MB 钳制到 64MB,然后,在收到大量不同的消息后...应用程序崩溃。
根据我阅读类似问题 (What might be the cause of "long monitor contention event with owner method"?) 的理解,问题是我正在接收大量事件并将事件锁定 "too much" 时间。
所以问题是...我能做什么?我可以通过保存我删除的最后一个位置并在下次从它开始 for 循环来优化它,但我认为这还不够。或者我可以为不同的事件做不同的队列,这样我总是删除第一个,但我总是需要锁定它。有更好的主意吗?
我忘了说我要声明:private LinkedList events = new LinkedList<>();
使用这个方法
public void enqueue(T event) {
List<T> removable = new ArrayList<>();
synchronized (events) {
final int size = events.size();
if (size > 2000) {
for (int i = 0; i < size; i++) {
final T t = events.get(i);
if (canRemove(t)) {
removable.add(t);
break;
}
}
}
if (removable.size() > 0) {
events.removeAll(removable);
}
events.add(event);
}
}
希望它能解决您的问题。
我认为您可以使用 events.subList
方法来代替删除对象,如下所示:
public void enqueue(T event) {
List<T> removable = new ArrayList<>();
synchronized (events) {
final int size = events.size();
if (size > 2000) {
int removeSize = events.size() - 2000;
events = events.subList(removeSize, events.size());
}
events.add(event);
}
}