condition和Lock锁一样出现在jdk1.5中的,它的出现使用来替代传统的Object的wait()/notify()方法,配合Lock锁实现线程间的协作的。
java.util.concurrent.locks包下常用的类与接口(jdk1.5中):

Lock 和 Thread 三者之间的关系如下图:

Condition中主要的方法包括:await()/signal(),它们分别对应Object中的wait()/notify()方法,Condition相比较Object方法提供了更安全、高效和灵活的线程间协作,condition依赖与Lock接口,condition通过Lock.newCondition创建,同时,Condition必须在Lock的保护内使用。在多线程的状态下,可以通过以condition实例为单位的通知等待机制的分组,只通知部分线程。
condition分组实例:
// 线程 A
class ThreadA extends Thread {
private MyService service;
public ThreadA(MyService service) {
super();
this.service = service;
}
@Override
public void run() {
service.awaitA();
}
}
// 线程 B
class ThreadB extends Thread {
private MyService service;
public ThreadB(MyService service) {
super();
this.service = service;
}
@Override
public void run() {
service.awaitB();
}
}
class MyService {
private Lock lock = new ReentrantLock();
// 使用多个Condition实现通知部分线程
public Condition conditionA = lock.newCondition();
public Condition conditionB = lock.newCondition();
public void awaitA() {
lock.lock();
try {
System.out.println("begin awaitA时间为" + System.currentTimeMillis()
+ " ThreadName=" + Thread.currentThread().getName());
conditionA.await();
System.out.println(" end awaitA时间为" + System.currentTimeMillis()
+ " ThreadName=" + Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void awaitB() {
lock.lock();
try {
System.out.println("begin awaitB时间为" + System.currentTimeMillis()
+ " ThreadName=" + Thread.currentThread().getName());
conditionB.await();
System.out.println(" end awaitB时间为" + System.currentTimeMillis()
+ " ThreadName=" + Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void signalAll_A() {
try {
lock.lock();
System.out.println(" signalAll_A时间为" + System.currentTimeMillis()
+ " ThreadName=" + Thread.currentThread().getName());
conditionA.signalAll();
} finally {
lock.unlock();
}
}
public void signalAll_B() {
try {
lock.lock();
System.out.println(" signalAll_B时间为" + System.currentTimeMillis()
+ " ThreadName=" + Thread.currentThread().getName());
conditionB.signalAll();
} finally {
lock.unlock();
}
}
}
public class ConditionTest {
public static void main(String[] args) throws InterruptedException {
MyService service = new MyService();
ThreadA a = new ThreadA(service);
a.setName("A");
a.start();
ThreadB b = new ThreadB(service);
b.setName("B");
b.start();
Thread.sleep(3000);
service.signalAll_A();
}
}
输出结果:
begin awaitA时间为1615804726283 ThreadName=A
begin awaitB时间为1615804726284 ThreadName=B
signalAll_A时间为1615804729284 ThreadName=main
end awaitA时间为1615804729284 ThreadName=A
我们可以看到只有A组被唤醒了,而B组依旧处于阻塞状态;
假如:我们使用一个condition实例进行线程间的协作会怎么样?
实例:
package thread;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class ThreadE extends Thread{
private MySingleService service;
public ThreadE(MySingleService service) {
super();
this.service = service;
}
@Override
public void run() {
service.awaitE();
}
}
class ThreadF extends Thread{
private MySingleService service;
public ThreadF(MySingleService service) {
super();
this.service = service;
}
@Override
public void run() {
service.awaitF();
}
}
class MySingleService{
private Lock lock = new ReentrantLock();
// 使用多个Condition实现通知部分线程
public Condition conditionE = lock.newCondition();
public void awaitE() {
lock.lock();
try {
System.out.println("begin awaitA时间为" + System.currentTimeMillis()
+ " ThreadName=" + Thread.currentThread().getName());
conditionE.await();
System.out.println(" end awaitA时间为" + System.currentTimeMillis()
+ " ThreadName=" + Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void awaitF() {
lock.lock();
try {
System.out.println("begin awaitB时间为" + System.currentTimeMillis()
+ " ThreadName=" + Thread.currentThread().getName());
conditionE.await();
System.out.println(" end awaitB时间为" + System.currentTimeMillis()
+ " ThreadName=" + Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void signalAll_E() {
try {
lock.lock();
System.out.println(" signalAll_A时间为" + System.currentTimeMillis()
+ " ThreadName=" + Thread.currentThread().getName());
conditionE.signalAll();
} finally {
lock.unlock();
}
}
}
public class SingleConditionTest {
public static void main(String[] args) throws InterruptedException {
MySingleService service = new MySingleService();
ThreadE e = new ThreadE(service);
e.setName("E");
e.start();
ThreadF f = new ThreadF(service);
f.setName("F");
f.start();
Thread.sleep(3000);
service.signalAll_E();
}
}
输出结果:
begin awaitA时间为1615804861481 ThreadName=E
begin awaitB时间为1615804861482 ThreadName=F
signalAll_A时间为1615804864482 ThreadName=main
end awaitA时间为1615804864482 ThreadName=E
end awaitB时间为1615804864482 ThreadName=F
我们发现两组线程都被唤醒了,所以Condition的分组机制是按照Condition实例来进行的;
同样,相比较Condition,Object提供的wait()/notify()方法也只能在synchronized,以下为对照组实例:
实例:
class ThreadC extends Thread{
private MyObjectService service;
public ThreadC(MyObjectService service) {
super();
this.service = service;
}
@Override
public void run() {
service.waitC();
}
}
class ThreadD extends Thread{
private MyObjectService service;
public ThreadD(MyObjectService service) {
super();
this.service = service;
}
@Override
public void run() {
service.waitD();
}
}
class MyObjectService{
public synchronized void waitC() {
try {
System.out.println("begin awaitC时间为" + System.currentTimeMillis()
+ " ThreadName=" + Thread.currentThread().getName());
this.wait();
System.out.println(" end awaitC时间为" + System.currentTimeMillis()
+ " ThreadName=" + Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public synchronized void waitD() {
try {
System.out.println("begin awaitD时间为" + System.currentTimeMillis()
+ " ThreadName=" + Thread.currentThread().getName());
this.wait();
System.out.println(" end awaitD时间为" + System.currentTimeMillis()
+ " ThreadName=" + Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public synchronized void notifyAll_C() {
try {
System.out.println(" notifyAll_C时间为:" + System.currentTimeMillis()
+ " ThreadName=" + Thread.currentThread().getName());
this.notifyAll();
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class ObjectThreadTest {
public static void main(String[] args) throws InterruptedException {
MyObjectService service = new MyObjectService();
ThreadC c = new ThreadC(service);
c.setName("C");
c.start();
ThreadD d = new ThreadD(service);
d.setName("D");
d.start();
Thread.sleep(3000);
service.notifyAll_C();
}
}
输出结果:
begin awaitC时间为1615804981351 ThreadName=C
begin awaitD时间为1615804981352 ThreadName=D
notifyAll_C时间为:1615804984353 ThreadName=main
end awaitD时间为1615804984353 ThreadName=D
end awaitC时间为1615804984353 ThreadName=C
Java并发:Condition的分组机制解析
本文介绍了Java中的Condition机制,它提供了一种替代传统Object.wait()和notify()的线程协作方式。Condition与Lock接口相关联,通过Lock.newCondition创建,并且必须在Lock的保护下使用。Condition的分组机制允许按照Condition实例来控制线程的唤醒,从而实现更加灵活和安全的线程协作。文中通过实例展示了如何使用Condition进行分组,以及对比了与Object.wait()和notify()的不同。
555

被折叠的 条评论
为什么被折叠?



