In order to deal with these issues I found sticking closely to the following principles helps me a lot.
- Don't ever run blocking or waiting operations on the FX-Thread - If you need to wait on some resource, do so by starting a separate thread or using an executor.
- Resources that are accessed by multiple threads need to have some form of lock - for example you can't have it happen that one thread iterates over a collection while another one updates it. The most simple form of resource control is creating a Semaphore with a single permit. This way any time you access the collection, you acquire it and after you are done you release it. That in combination with the first principle allows you to write logic freely.