Android游戏中LinkedList.toArray()报ArrayIndexOutOfBoundsException问题求助
Hey there! Let's break down why you're hitting that ArrayIndexOutOfBoundsException in your game code—even though you expect an empty array when remoteQueue is empty.
The Root Cause: Concurrent Modification
LinkedList isn't thread-safe, and that's almost certainly the issue here. Here's what's likely happening:
When your code calls toArray(new RemoteVariable[0]), the method first checks the queue's size to create a matching-length array. But if another thread adds or removes elements after the size check but before the array is fully populated, the array length won't line up with the actual number of elements—triggering the out-of-bounds error.
Even if remoteQueue was empty when you started, another thread could sneak in elements mid-execution, breaking your expected behavior. Plus, the toArray() and clear() calls aren't atomic, leaving a window for race conditions to mess things up.
Solutions to Fix the Issue
1. Switch to a Thread-Safe Queue
The simplest fix is to replace LinkedList with ConcurrentLinkedQueue, a thread-safe implementation built for concurrent access. It handles synchronization under the hood, so you won't run into race conditions or array bounds errors:
// Replace your LinkedList declaration with this private Queue<RemoteVariable> remoteQueue = new ConcurrentLinkedQueue<>(); public RemoteVariable[] getRemoteVariable(){ RemoteVariable[] variables = remoteQueue.toArray(new RemoteVariable[0]); remoteQueue.clear(); return variables; }
2. Add Synchronization Locks (If You Must Keep LinkedList)
If you need to stick with LinkedList, wrap all access to the queue in a synchronized block. This ensures toArray() and clear() run as a single atomic operation. Make sure every place that modifies or reads remoteQueue uses the same lock:
private LinkedList<RemoteVariable> remoteQueue = new LinkedList<>(); // Create a dedicated lock object private final Object queueLock = new Object(); public RemoteVariable[] getRemoteVariable(){ synchronized(queueLock) { RemoteVariable[] variables = remoteQueue.toArray(new RemoteVariable[0]); remoteQueue.clear(); return variables; } } // Example: Any method adding to the queue must also use the lock public void addRemoteVariable(RemoteVariable var) { synchronized(queueLock) { remoteQueue.add(var); } }
3. Initialize the Array with Queue Size (With Lock)
Another tweak (still requiring synchronization) is to initialize the array using the queue's current size. This avoids the internal resizing that can go wrong with concurrent changes:
synchronized(queueLock) { RemoteVariable[] variables = remoteQueue.toArray(new RemoteVariable[remoteQueue.size()]); remoteQueue.clear(); return variables; }
Quick Note for Android Games
Since Android games often use multiple threads (e.g., background logic threads sending data to the main thread), thread-safe collections are your best bet to avoid these hard-to-debug concurrency issues. ConcurrentLinkedQueue is lightweight and perfect for this use case.
内容的提问来源于stack exchange,提问作者Bartors

