What you want to do is think in terms of frames. Update everything every frame (e.g 1/60th of a second) then sleep till the next frame (an animal doesn't have to do anything when its updated, its just given the opportunity to).
So say that one rabbit moves then needs to rest for 2 seconds before moving again. Each rabbit would have an instance variable of restTime
which it would set to 2 seconds after making a move. Each frame it would reduce this variable by the frame time (1/60th of a second). When the variable is zero or less it moves again. This means that you can do it all one one thread and the animals movements are not dependant on each other (except for when you want them to be of course).
If you're animating this it's best to measure the actual frame time and use that rather than assuming you'll actually get exactly the 1/60th of a second you asked for.
An example might be as follows
public class Rabbit {
private double timeBetweenMoves;
private double sleepTime=0;
private String name;
public Rabbit(String name,double timeBetweenMoves) {
this.name=name;
this.timeBetweenMoves=timeBetweenMoves;
}
public void update(double timeSlice){
sleepTime-=timeSlice;
if (sleepTime<0){
makeMove();
}
}
private void makeMove(){
sleepTime=timeBetweenMoves;
//actually make the move
System.out.println(name + " Moved");
}
public static void main(String[] args){
double frameTime=1/60.0;
List<Rabbit> rabbits=new ArrayList<>();
rabbits.add(new Rabbit("Floppsy",2)); //moves every 2 seconds
rabbits.add(new Rabbit("Hopper",5)); //moves every 5 seconds
while(true){
for(Rabbit rabbit:rabbits){
rabbit.update(frameTime); //assumes frametime is actually what you asked for, can cause graphics to look stuttery
}
try {
long milllisecondsToSleep=(long)(frameTime*1000);
Thread.sleep(milllisecondsToSleep);
} catch (InterruptedException ex) {
Logger.getLogger(Rabbit.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}