new SampleClass().start().join(); This is wrong.
你可以通过
   SampleClass samClass = new SampleClass();
   samClass.start();
   samClass.join()
上面的代码将具有与您想要的相同的效果。
现在您的问题是按顺序运行线程。在大多数情况下,您不需要线程按顺序执行(但是有一些场景)。好吧,如果你必须这样做。 
然后你可以这样做
   Thread t1 = ..
   Thread t2 = ..
   t1.start();
   t1.join();
   t2.start(); // t2 will start only when t1 dies
   t2.join(); //  
   t3.start(); // t3 will start only when t2 dies..
但上述方法并不好。因为要启动其他线程,前一个线程需要死亡。在实践中我们应该将创建线程视为一项昂贵的操作并尝试重用.
真正的问题通常是这样的,您必须按顺序执行任务 T1 、 T2 、 T3 、 T4 ,但在不同的线程中 T1 && T3 必须在一个线程上运行,而 T2 和 T4 必须在另一个线程上运行。所以在这里我们可以使用两个线程而不是 4 个线程。 Thread1 将运行 T1,然后 Thread2 将运行 T2,然后 Thread1 将运行 T3,依此类推,即
Thread1 -> T1
Thread2 -> T2
Thread1 -> T3
Thread2 -> T4
所有任务将按顺序执行,但仅使用 2 个线程。
您可以解决如下问题
  Thread1 ->run {
    while(canIrun) {
    executeTask(taskQueue1.next());
    notifyThread2();
    waitForThread2Signal();
   }
  }
  Thread2 -.run {
   while(canIrun) {
    waitForThread1Signal();
    executeTask(taskQueue2.next());
    notifyThread1();
   }
  }
使用 CyclicBarrier 可以很容易地实现 wait 和 notify 方法。