目录
二、在 T2 线程中 T1.join,在 T3 线程中 T2.join,类似循环嵌套;
三、用线程池,线程池大小就1个----用newSingleThreadExecutor线程池
情况描述:T1、T2、T3三个线程若无控制,执行顺序是乱的;
一、 join() 方法
Thread类中的join方法的主要作用就是同步,它可以使得线程之间的并行变串行。当我们调用某个线程的这个方法时,这个方法会挂起调用线程,直到被调用线程结束执行,调用线程才会继续执行。
二、在 T2 线程中 T1.join,在 T3 线程中 T2.join,类似循环嵌套;
三、用线程池,线程池大小就1个----用newSingleThreadExecutor线程池
四、信号量
Semaphore信号量对象,可以存放N个信号量,可以原子性的释放和请求这N个信号量,我们先预设两个存放0个信号量的对象,
非预期顺序的线程启动后,无法获取到信号量,进入等待,直到前序线程释放信号量。
注意:Semaphore中可以为负值,这时候,就必须确保release发生在acquire前面,比如Semaphore(0)和Semaphore(-1)的情况:
Semaphore(-1)的release可以,require则进入休眠,Semaphore(0)的release可以,require则进入休眠,即只有permit大于0时,才能require成功!
五、lock配合condition
private static final Lock lock = new ReentrantLock();
private static final Condition condition1 = lock.newCondition();
private static final Condition condition2 = lock.newCondition();
private static Boolean t1Run = false;
private static Boolean t2Run = false;
public static void main(String[] args) {
final Thread thread1 = new Thread(
()->{
// 注意lock/tryLock的区别: lock是void,没获取到锁,则进入休眠,tryLock是返回Boolean,执行后立即返回true/false
lock.lock();
System.out.println("先买菜");
//在等待队列中唤醒一个线程
condition1.signal();
t1Run = true;
// 生产环境下这里最好使用try/finally确保unlock执行
lock.unlock();
}
);
final Thread thread2 = new Thread(
()->{
lock.lock();
try {
if (!t1Run){
condition1.await();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("再煎蛋");
t2Run = true;
condition2.signal();
lock.unlock();
}
);
final Thread thread3 = new Thread(
()->{
lock.lock();
try {
if (!t2Run){
condition2.await();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("后吃饭");
lock.unlock();
}
);
thread3.start();
thread2.start();
thread1.start();
}