To kill off the agents thread can't you just feed them a runnable that ends when the model ends?
To kill off the display associated with them, tell the agents thread, right before it ends, to release a permit to an external (and initially empty)
semaphore. Tell the thread calling dispose() on the jframe to acquire X (number of agents) permits from the semaphore before killing the jframe and it should coordinate by itself.
Understand however that concurrency is easy to screw up and you might want to bone up on it rather than trusting my foggy memories of it.