让线程顺序执行的七种方法:
- 使用线程的join方法实现
- 使用锁对象的wait与notify方法实现
- 使用newSingleThreadExecutor或者newSingleThreadScheduledExecutor实现
- 使用Condition的await与signal方法实现
- 使用CountDownLatch的countDown与await方法实现
- 使用CyclicBarrier的await方法实现
- 使用Semaphore的acquire与release方法实现,定义数量为0的信号量,当前需要阻塞的线程先acquire,前面线程执行完毕后release
方法一:使用线程的join方法实现
join():是Theard的方法,作用是调用线程需等待该join()线程执行完成后,才能继续用下运行。
应用场景:当一个线程必须等待另一个线程执行完毕才能执行时可以使用join方法。
public class ThreadJoinDemo {
public static void main(String[] args) {
final Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("产品经理规划新需求");
}
});
final Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
try {
thread1.join();
System.out.println("开发人员开发新需求功能");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread thread3 = new Thread(new Runnable() {
@Override
public void run() {
try {
thread2.join();
System.out.println("测试人员测试新功能");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
System.out.println("早上:");
System.out.println("测试人员来上班了...");
thread3.start();
System.out.println("产品经理来上班了...");
thread1.start();
System.out.println("开发人员来上班了...");
thread2.start();
}
}
方法二:使用锁对象的wait与notify方法实现
public class ThreadWaitDemo {
private static Object myLock1 = new Object();
private static Object myLock2 = new Object();
/**
* 为什么要加这两个标识状态? 如果没有状态标识,当t1已经运行完了t2才运行,t2在等待t1唤醒导致t2永远处于等待状态
*/
private static Boolean t1Run = false;
private static Boolean t2Run = false;
public static void main(String[] args) {
final Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
synchronized (myLock1) {
System.out.println("产品经理规划新需求...");
t1Run = true;
myLock1.notify();
}
}
});
final Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
synchronized (myLock1) {
try {
if (!t1Run) {
System.out.println("开发人员先休息会...");
myLock1.wait();
}
synchronized (myLock2) {
System.out.println("开发人员开发新需求功能");
myLock2.notify();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
Thread thread3 = new Thread(new Runnable() {
@Override
public void run() {
synchronized (myLock2) {
try {
if (!t2Run) {
System.out.println("测试人员先休息会...");
myLock2.wait();
}
System.out.println("测试人员测试新功能");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
thread3.start();
thread1.start();
thread2.start();
}
}
方法三:使用newSingleThreadExecutor或者newSingleThreadScheduledExecutor实现
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolDemo {
static ExecutorService executorService = Executors.newSingleThreadExecutor();
// static ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
public static void main(String[] args) throws Exception {
final Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("产品经理规划新需求");
}
});
final Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
try {
// 为了验证thread3确实在thread2后执行
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("开发人员开发新需求功能");
}
});
Thread thread3 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("测试人员测试新功能");
}
});
System.out.println("早上:");
System.out.println("产品经理来上班了");
System.out.println("测试人员来上班了");
System.out.println("开发人员来上班了");
System.out.println("领导吩咐:");
System.out.println("首先,产品经理规划新需求...");
executorService.execute(thread1);
System.out.println("然后,开发人员开发新需求功能...");
executorService.execute(thread2);
System.out.println("最后,测试人员测试新功能...");
executorService.execute(thread3);
executorService.shutdown();
}
}
方法四:使用Condition的await与signal方法实现
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ThreadConditionDemo {
private static Lock lock = new ReentrantLock();
private static Condition condition1 = lock.newCondition();
private static Condition condition2 = lock.newCondition();
/**
* 为什么要加这两个标识状态?
* 如果没有状态标识,当t1已经运行完了t2才运行,t2在等待t1唤醒导致t2永远处于等待状态
*/
private static Boolean t1Run = false;
private static Boolean t2Run = false;
public static void main(String[] args) {
final Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
lock.lock();
System.out.println("产品经理规划新需求");
t1Run = true;
condition1.signal();
lock.unlock();
}
});
final Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
lock.lock();
try {
if(!t1Run){
System.out.println("开发人员先休息会...");
condition1.await();
}
System.out.println("开发人员开发新需求功能");
t2Run = true;
condition2.signal();
} catch (InterruptedException e) {
e.printStackTrace();
}
lock.unlock();
}
});
Thread thread3 = new Thread(new Runnable() {
@Override
public void run() {
lock.lock();
try {
if(!t2Run){
System.out.println("测试人员先休息会...");
condition2.await();
}
System.out.println("测试人员测试新功能");
lock.unlock();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
System.out.println("早上:");
System.out.println("测试人员来上班了...");
thread3.start();
System.out.println("产品经理来上班了...");
thread1.start();
System.out.println("开发人员来上班了...");
thread2.start();
}
}
方法五:使用CountDownLatch的countDown与await方法实现
import java.util.concurrent.CountDownLatch;
public class ThreadCountDownLatchDemo {
/**
* 用于判断线程一是否执行,倒计时设置为1,执行后减1
*/
private static CountDownLatch c1 = new CountDownLatch(1);
/**
* 用于判断线程二是否执行,倒计时设置为1,执行后减1
*/
private static CountDownLatch c2 = new CountDownLatch(1);
public static void main(String[] args) {
final Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("产品经理规划新需求");
// 对c1倒计时-1
c1.countDown();
}
});
final Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
try {
// 等待c1倒计时,计时为0则往下运行
c1.await();
System.out.println("开发人员开发新需求功能");
// 对c2倒计时-1
c2.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread thread3 = new Thread(new Runnable() {
@Override
public void run() {
try {
// 等待c2倒计时,计时为0则往下运行
c2.await();
System.out.println("测试人员测试新功能");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
System.out.println("早上:");
System.out.println("测试人员来上班了...");
thread3.start();
System.out.println("产品经理来上班了...");
thread1.start();
System.out.println("开发人员来上班了...");
thread2.start();
}
}
方法六:使用CyclicBarrier的await方法实现
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class CyclicBarrierDemo {
static CyclicBarrier barrier1 = new CyclicBarrier(2);
static CyclicBarrier barrier2 = new CyclicBarrier(2);
public static void main(String[] args) {
final Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
try {
System.out.println("产品经理规划新需求");
// 放开栅栏1
barrier1.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
});
final Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
try {
// 放开栅栏1
barrier1.await();
System.out.println("开发人员开发新需求功能");
// 放开栅栏2
barrier2.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
});
final Thread thread3 = new Thread(new Runnable() {
@Override
public void run() {
try {
// 放开栅栏2
barrier2.await();
System.out.println("测试人员测试新功能");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
});
System.out.println("早上:");
System.out.println("测试人员来上班了...");
thread3.start();
System.out.println("产品经理来上班了...");
thread1.start();
System.out.println("开发人员来上班了...");
thread2.start();
}
}
方法七:使用Semaphore的acquire与release方法实现,定义数量为0的信号量,当前需要阻塞的线程先acquire,前面线程执行完毕后release
import java.util.concurrent.Semaphore;
public class SemaphoreDemo {
private static Semaphore semaphore1 = new Semaphore(0);
private static Semaphore semaphore2 = new Semaphore(0);
public static void main(String[] args) {
final Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("产品经理规划新需求");
semaphore1.release();
}
});
final Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
try {
semaphore1.acquire();
System.out.println("开发人员开发新需求功能");
semaphore2.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread thread3 = new Thread(new Runnable() {
@Override
public void run() {
try {
semaphore2.acquire();
System.out.println("测试人员测试新功能");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
System.out.println("早上:");
System.out.println("测试人员来上班了...");
thread3.start();
System.out.println("产品经理来上班了...");
thread1.start();
System.out.println("开发人员来上班了...");
thread2.start();
}
}