Exemple

public static final Boolean lock = Boolean.TRUE;

public static void main( String[] args ) {
Runnable runnable = new Runnable() {
public void run() {
synchronized ( lock ) {
while ( true ) {
System.out.println( "Hello World!" ); //$NON-NLS-1$
try { wait( 1000 ); } catch (InterruptedException e) {}
}
}
}
};
Thread thread = new Thread(runnable);
thread.start();
try { Thread.sleep( 3000 ); } catch (InterruptedException e) {}
thread.stop();
}

Solution
Voici un extrait (traduit librement) de la documentation Java (copyright by Sun Microsystems)
Dans de nombreux cas, il conviendra de remplacer stop par du code qui modifie simplement une certaine variable de de façon à indiquer que l'exécution de l'unité cible doit prendre fin.
L'unité cible devra régulièrement vérifier cette variable et quitter "proprement" sa méthode d'exécution si la variable indique que l'exécution doit être interrompue. En cas de longues périodes d'attente pour l'unité cible (présence d'une variable de condition, par exemple), il y aura lieu d'utiliser la méthode d'interruption pour pour mettre fin à cette attente.
Utilisez StopSafeRunnable.

public static abstract class StopSafeRunnable implements Runnable {
public final void run() {
while ( !stopped ) {
doRun();
}
}
public void stop() {
stopped = true;
}
public boolean isStopped() {
return stopped;
}
protected abstract void doRun();

private boolean stopped = false;
}

public static void main(String[] args) {
StopSafeRunnable runnable = new StopSafeRunnable() {
public void doRun() {
System.out.println( "Hello World" ); //$NON-NLS-1$
try { Thread.sleep( 1000 ); } catch (InterruptedException e) {}
}
};
Thread thread = new Thread(runnable);
thread.start();
try { Thread.sleep( 3000 ); } catch (InterruptedException e) {}
runnable.stop();
}