这是我参与8月更文挑战的第8天,活动详情查看:8月更文挑战
Condition
由ReentrantLock
对象创建,并且可以同时创建多个,Condition
接口在使用前必须先调用ReentrantLock
的lock()
方法获得锁,之后调用Condition
接口的await()
将释放锁,并且在该Condition
上等待,直到有其他线程调用Condition
的signal()
方法唤醒线程。
案例:
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
/**
* Description:
*
* @author jack
* @date 2021/8/12 11:13 上午
*/
public class ConditionTest {
static ReentrantLock lock = new ReentrantLock();
static Condition condition1 = lock.newCondition();
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(() -> {
lock.lock();
try {
System.out.println(System.currentTimeMillis() + " " + Thread.currentThread().getName() + "调用await");
condition1.await();
System.out.println(System.currentTimeMillis() + " " + Thread.currentThread().getName() + "被唤醒");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
});
Thread t2 = new Thread(() -> {
lock.lock();
try {
System.out.println(System.currentTimeMillis() + " " + Thread.currentThread().getName() + "调用signal");
condition1.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
});
t1.setName("t1");
t1.start();
TimeUnit.SECONDS.sleep(1);
t2.setName("t2");
t2.start();
}
}
输出结果
1629253423621 t1调用await
1629253424621 t2调用signal
1629253424621 t1被唤醒
当使用Condition.await()
方法时,需要先获取Condition
对象关联的ReentrantLock
的锁,在Condition.await()
方法被调用时,当前线程会释放这个锁,并且当前线程会进行等待(处于阻塞状态)。在signal()
方法被调用后,系统会从Condition
对象的等待队列中唤醒一个线程,一旦线程被唤醒,被唤醒的线程会尝试重新获取锁,一旦获取成功,就可以继续执行了。因此,在signal()
被调用后,一般需要释放相关的锁,让给其他被唤醒的线程,让他可以继续执行。
Condition.await()
和Condition.signal()
在调用时 必须先获取锁再调用 不然会抛出java.lang.IllegalMonitorStateException
异常
使用Condition
实现精准唤醒
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
/**
* Description:
*
* @author jack
* @date 2021/8/12 11:13 上午
*/
public class ConditionTest {
static ReentrantLock lock = new ReentrantLock();
static Condition condition1 = lock.newCondition();
static Condition condition2 = lock.newCondition();
static Condition condition3 = lock.newCondition();
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(() -> {
lock.lock();
try {
System.out.println(System.currentTimeMillis() + " " + Thread.currentThread().getName() + "调用await");
condition1.await();
System.out.println(System.currentTimeMillis() + " " + Thread.currentThread().getName() + "被唤醒");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
});
Thread t2 = new Thread(() -> {
lock.lock();
try {
System.out.println(System.currentTimeMillis() + " " + Thread.currentThread().getName() + "调用condition1.signal()");
condition1.signal();
System.out.println(System.currentTimeMillis() + " " + Thread.currentThread().getName() + "调用await");
condition2.await();
System.out.println(System.currentTimeMillis() + " " + Thread.currentThread().getName() + "被唤醒");
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
});
Thread t3 = new Thread(() -> {
lock.lock();
try {
System.out.println(System.currentTimeMillis() + " " + Thread.currentThread().getName() + "调用condition2.signal()");
condition2.signal();
System.out.println(System.currentTimeMillis() + " " + Thread.currentThread().getName() + "调用await");
condition3.await();
System.out.println(System.currentTimeMillis() + " " + Thread.currentThread().getName() + "被唤醒");
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
});
t1.setName("t1");
t1.start();
TimeUnit.SECONDS.sleep(1);
t2.setName("t2");
t2.start();
TimeUnit.SECONDS.sleep(1);
t3.setName("t3");
t3.start();
TimeUnit.SECONDS.sleep(1);
lock.lock();
try {
System.out.println(System.currentTimeMillis() + " " + Thread.currentThread().getName() + "调用condition3.signal()");
condition3.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
输出结果
1629255550850 t1调用await
1629255551853 t2调用condition1.signal()
1629255551853 t2调用await
1629255551853 t1被唤醒
1629255552856 t3调用condition2.signal()
1629255552856 t3调用await
1629255552857 t2被唤醒
1629255553855 main调用condition3.signal()
1629255553855 t3被唤醒
测试场景是 main
线程来唤醒t3
线程 t3
线程来唤醒t2
线程 t2
线程来唤醒t1
线程