Originariamente inviato da esploratore8
Quindi??? come dovrei fare...
Ok, vediamo di fare qualche altra ipotesi per una soluzione migliore. Cercherò di spiegarlo a parole e in modo meno tecnico possibile.

Innanzitutto fino ad adesso Characters è un Thread con un proprio run() in cui fai "avanzare" lo stato della animazione, in pratica incrementi la Y ogni tot di tempo. Hai più oggetti Characters e ne consegue altrettanti thread.

Proviamo a spostare il thread e a farne 1 solo! Il thread potrebbe essere gestito in CustomPanel e il suo run() dovrebbe ripetere in sequenza infinita (come chiedevi) le seguenti cose:

1) attesa di un tot di tempo
2) "avanzamento" dei vari Characters
3) repaint
quindi si riparte da 1)

per "avanzamento" dei vari Characters intendo una cosa molto semplice. In Characters non c'è più un thread ma un semplice metodo es. avanza() in cui tu esegui le operazioni necessarie affinché il Characters passi ad uno stato successivo, il che nel tuo caso vuol poi dire che si incrementa con una qualche logica quella Y.
Characters non deve fare molto altro, quel draw() va bene e serve appunto per disegnare la entità da rappresentare.
Per dirla in modo semplice, Characters offre 2 operazioni (come minimo): "avanza" e "disegnati". Tutto qua.

Come ho detto sopra, CustomPanel gestisce un solo thread, il repaint() non lo devi più fare in paintComponent() (che come ho già detto non è una bella cosa) ma durante la esecuzione del thread. Il resto di paintComponent() va bene, ovvero invocazione del super di paintComponent() e disegno dei vari oggetti nella lista.

Rimane ancora la questione della concorrenza: l'avanzamento lo fai nel contesto di un thread a parte mentre il draw viene fatto nel contesto del EDT (il paintComponent() viene invocato da Swing ... non da te direttamente!). Ma si può risolvere.

Come vedi abbiamo "girato" un pochino le cose. Come ti sembra? Più semplice o più difficile? Prova a pensarci e magari a modificare il codice. Se hai dubbi, ovviamente chiedi pure.