@WYSIWYG link seems to have a wealth of useful patterns but i can give you some guidelines to follow. The main source of problems with Multi-Threaded programs is Update Operations or Concurrent Modification and some of the less occurring problems are Starvation, Deadlocks , etc which are more deadly if i may say, so to avoid these situations you can:
- Make use of the Immutable Object pattern, if an object can't be modified after creation then you can't have uncoordinated updates and as we know the creation operation itself is guaranteed to be atomic by the JVM in your case.
- Command Query Segregation Principle: that is separate code that modifies the object from code that reads them because reading can happen concurrently but modification can't.
- Take huge benefit of the language and library features you are using such as concurrent lists and threading structures because they are well designed and have good performance.
- There is a book (although an old one) but with very good designs for such systems, it is called Concurrent Programming in Java.