Now as I understand dynamic and threading are conflicting with each other. I cannot issue all these order simultaneously since unit A might go for the same item as Unit B and things will obviously break. How can I deal with this in a proper way?
As usual, there is no one true way.
The first thing I'll recommend is that, where possible, do not share mutable state between threads using manual locking. This is one of the most complex ways to implement multi-threading, and maintaining the correctness of such an approach is going to be a major challenge. It is actually possible to write multi-threaded code that performs slower than similar single threaded code if this is done wrong, along with risking deadlocking, etc.
Instead, prefer:
- Immutable data structures. Once created, the data can be safely shared between threads/ For example, your basic map layout might fit into this category.
- Creating copies of mutable state. For example, where the items, buildings and units are at a given time step.
- Communicating via established thread-safe data structures.
Let's imagine you already have a single-threaded version of the code that is working correctly. Here is one way you could evolve that into something that can be pushed into a background thread. I'm not saying this is the best way or that you would have to actually follow these steps prescriptively, but it hopefully will illustrate a way around the issue you identified. In particular, I've not done path finding so there might be more specific techniques that are better suited to that problem.
The first thing is to change your existing code so that it can execute out of order. So, for the example you cited, when the user orders a stockpile, create an object that represents this command and place it in a queue (e.g. "find the nearest sword at map location X, Y"). Then, between time steps, pop one or more tasks from this queue, execute the path finding logic and store an object that describes the results of the path finding computation in another queue (e.g. "the nearest sword to X, Y was at XX, YY"). Inside the game logic, pop any completed results and attempt to take the action (you'll need some way of linking the commands with the results). If you find that the results have been invalidated (e.g. that sword object has moved or otherwise unavailable), you can just throw that computation away and re-issue the command. It will depend on the game, but for most such games, the user won't be issuing so many orders that there will be a lot of wasted work.
At this point, consider stopping and evaluate the resulting gameplay experience. It might be that with the right tuning on how many commands are popped from the queues per timestep, you have achieved a responsive user interface by essentially limiting the amount of CPU time that pathfinding can consume each timestep. If so, mission accomplished - you don't need to add multi-threading!
Should you want or need to continue, the next step is to ensure that these tasks could execute safely on a background thread. Let's assume the basic map layout is be immutable and safely shareable. For state that is mutable, consider having a separate copy for the background task. For example, maybe every time step, the foreground game logic thread will push "building created", "item reserved" and "unit moved" events into a queue. Between computations, the background thread can drain this queue and apply the events to a local copy of the game state.
It should be possible to test an implementation of this design without introducing multiple threads yet.
Finally, you can push the work into the background. You'll need to ensure that you use thread-safe queuing data structures. Java has standard classes for this, such as the Queue classes in the "java.util.concurrent" package. You'll also need to ensure that your command, result and event objects are thread-safe (e.g. not holding a reference to state that could be accessed by other threads).
You'll want to avoid creating threads on demand. Threads are expensive to create, so unless the task is very rare and very expensive, it isn't worth creating a new threads for a single task. You could create a single background thread at startup that is hooked up to these queues. Ideally, it would block when the queue is empty.
This kind of design can allow you to have multiple concurrent pathfinding computations, you could create several background threads, each with a local copy of the relevant gamestate - you'd just need to adjust how update events are propagated. This way you can use a "thread pool", where a number of threads are created at startup and are "blocked" on a thread-safe work delivery queue. The number of threads can be configured to be appropriate to the user's machine. Again, the Java standard library has classes for this, the "ThreadPoolExecutor". This might be especially valuable if you have other interesting, expensive tasks that can be made asynchronous and pushed into the background.
If you have other expensive computations that can be made asynchronous, they could potentially share the same thread pool. You can use Futures if you prefer the API they provide. In the example above, I talk about an explicit command and result objects, but that is mostly to illustrate that you have to be careful how you pass data between threads, if you have a Sword class with a mutable Position, then passing that to the background thread is not safe.