Ti posto la mia soluzione, con un codice facilmente customizzabile.
- thread T1 con frequenza 1 secondo ed esecuzione totale 3 secondi
- thread T2 con frequenza 1 secondo ed esecuzione totale 4 secondi

codice:
import java.util.concurrent.*;
import static java.util.concurrent.TimeUnit.*;

class T1 implements Runnable {
    public void run() {
        System.out.println("T1");
    }
}

class T2 implements Runnable {
    public void run() {
        System.out.println("T2");
    }
}

class Demo {
    private ScheduledExecutorService scheduler =
       Executors.newScheduledThreadPool(1);
    private ScheduledFuture<?> t1Handle, t2Handle;

    public Demo() {
        StopT2StartT1();
    }
         
    private void StopT2StartT1() {
        if (t2Handle != null)
            t2Handle.cancel(true);    
        // T1: frequenza 1 secondo
        t1Handle = scheduler.scheduleAtFixedRate(new T1(), 0, 1, SECONDS);
        // 3 secondi di esecuzione totale
        scheduler.schedule(new Runnable() {
            public void run() {
                StopT1StartT2();
            }
        }, 3, SECONDS);  
    }
    
    private void StopT1StartT2() {
        t1Handle.cancel(true);
        // T2: frequenza 1 secondo
        t2Handle = scheduler.scheduleAtFixedRate(new T2(), 0, 1, SECONDS);
        // 4 secondi di esecuzione totale
        scheduler.schedule(new Runnable() {
            public void run() {
                StopT2StartT1();
            }
        }, 4, SECONDS);        
    }
         
    public static void main(String args[]) {
        new Demo();
    }
 }