什么是Condition?
条件队列:一个锁,可以创建多个队列
- 可以将多个线程存入对应的多个队列中,然后实现精准唤醒
一个锁,默认对应一个等待队列
当获取锁失败时,就会将此线程添加到队列中等待
当创建了Condition后,就可以实现一个锁,对应多个等待队列
private Lock lock = new ReentrantLock();
private Condition condition1 = lock.newCondition();
private Condition condition2 = lock.newCondition();
当获取锁失败时,就会将此线程放入属于它自己的队列中等待,当想唤醒此类线程的时候,就可以在此队列中精准唤醒(因为这个队列中都是一类的线程,所以唤醒任意一个都可以)
实现生产者消费者问题
public class Gold {
private Integer id;
private String manufacturer;
public Gold() {
}
public Gold(Integer id, String manufacturer) {
this.id = id;
this.manufacturer = manufacturer;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getManufacturer() {
return manufacturer;
}
public void setManufacturer(String manufacturer) {
this.manufacturer = manufacturer;
}
@Override
public String toString() {
return "Gold{" +
"id=" + id +
", manufacturer='" + manufacturer + '\'' +
'}';
}
}
package com.robot.juc.lock;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* @author 张宝旭
*/
public class Factory {
private Gold[] golds = new Gold[6];
private int size;
private Lock lock = new ReentrantLock();
private Condition condition1 = lock.newCondition();
private Condition condition2 = lock.newCondition();
public void put(Gold gold) {
lock.lock();
try {
while (size >= golds.length) {
try {
condition1.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
golds[size++] = gold;
System.out.println(Thread.currentThread().getName() + " 生成了 " + gold.getId() + " 号产品");
condition2.signal();
} finally {
lock.unlock();
}
}
public void take() {
lock.lock();
try {
while (size <= 0) {
try {
condition2.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
size--;
System.out.println(Thread.currentThread().getName() + " 消费了 " + golds[size].getId() + " 号产品");
golds[size] = null;
condition1.signal();
} finally {
lock.unlock();
}
}
}
package com.robot.juc.lock;
/**
* @author 张宝旭
*/
public class FactoryTest {
public static void main(String[] args) {
Factory factory = new Factory();
Runnable producer = () -> {
for(int i = 0; i < 10; i++) {
factory.put(new Gold(i, Thread.currentThread().getName()));
}
};
Runnable consumer = () -> {
for(int i = 0; i < 10; i++) {
factory.take();
}
};
Thread thread1 = new Thread(producer, "生产者A");
Thread thread2 = new Thread(producer, "生产者B");
Thread thread3 = new Thread(consumer, "消费者A");
Thread thread4 = new Thread(consumer, "消费者B");
thread1.start();
thread2.start();
thread3.start();
thread4.start();
}
}
面试题:连续输出”ABC“ 20次
package com.robot.juc.lock;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* @author 张宝旭
*/
public class Function {
private Lock lock = new ReentrantLock();
private Condition conditionA = lock.newCondition();
private Condition conditionB = lock.newCondition();
private Condition conditionC = lock.newCondition();
private char next = 'A';
public void printA() {
lock.lock();
try {
while (next != 'A') {
try {
conditionA.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("A");
next = 'B';
conditionB.signal();
} finally {
lock.unlock();
}
}
public void printB() {
lock.lock();
try {
while (next != 'B') {
try {
conditionB.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("B");
next = 'C';
conditionC.signal();
} finally {
lock.unlock();
}
}
public void printC() {
lock.lock();
try {
while (next != 'C') {
try {
conditionC.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("C");
next = 'A';
conditionA.signal();
} finally {
lock.unlock();
}
}
}
package com.robot.juc.lock;
/**
* @author 张宝旭
*/
public class FunctionTest {
public static void main(String[] args) {
Function function = new Function();
new Thread(()->{
for(int i = 0; i < 20; i++) {
function.printA();
}
}).start();
new Thread(()->{
for(int i = 0; i < 20; i++) {
function.printB();
}
}).start();
new Thread(()->{
for(int i = 0; i < 20; i++) {
function.printC();
}
}).start();
}
}