It seems you are doing too much on the Event Dispatch Thread (EDT). AWT-Event-Queue-0 looks to be the EDT. Additionally, your last comment says
...it seems the lag spike only occurs when I draw my game board to an image first rather than directly to the component.
You'll need to push some of your computations to other threads, and it sounds like drawing the game board is a good choice for this. Also, any AI you may have.
Your keyboard & mouse handlers run on the EDT, and the graphics updates need to too. But you can pre-render to an image (like you are currently doing) outside the EDT. And you can send the keyboard & mouse events to another thread via a BlockingQueue.
One other thing you could do is decouple your game-update rate from your frame-update rate.
But without any details, I can't give much more advice.
Update: (just read your bit about ConcurrentModificationException
)
This can be caused by two different things:
- you are updating a collection (like your ArrayList) in a different thread from the one you are reading it in; or
- you are iterating through said collection and updating it in the loop.
Point 2 is easy to fix; but I'm afraid I can't teach thread safety in such a short amount of space.