Allora devi agire in un altro modo:
devi passare a ThreadCompute un riferimento al thread che lo lancia e non attendere il tempo di millis in un sol colpo ma ad ogni millisecondo:
codice:
// Nel thread principale
private int tempo;
private boolean flag;
public ThreadPrincipale() { flag = true; ... }
public void run() {
        ThreadCompute q = new ThreadCompute(this); // Qui passo il riferimento
        q.setDaemon(true);
        q.start();//faccio partire il metodo
        try {
            while (flag && tempo<timer) {
               tempo++;
               sleep(1);  // Attendo un millisecondo prima di effettuare nuovamente il controllo
            }
        } catch (InterruptedException e) {
            
        }
        //Se è ancora vivo mando l'interrupt
        if(q.isAlive()) q.interrupt();

}

public void ferma() { flag = false; }
Nel ThreadCompute il codice sarà questo:
codice:
public class ThreadCompute {
   private ThreadPrincipale tp;
   public ThreadCompute(ThreadPrincipale tp) { this.tp = tp; }

   public void run() {
      ... // La tua elaborazione
      // Ultima riga del metodo run()
      tp.ferma();
   }
}
In questo modo se il ThreadCompu ha finito la sua elaborazione, ferma anche il thread principale, altrimenti sarà il thread principale a fermare ThreadCompu.


Ciao.