package function.thread;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
功能:三个生产者,往容量最大为5的容器里put数据
三个消费者从容器中取数据。只要容器不为空,就可以取数据,
只要容器不满,就可以存放数据
容器里不能拥有相同的数据
*/
public class ConditionTest {
public static void main(String args[]) {
final String goonFlag[] = {"true"};
final BoundedBuffer bf = new BoundedBuffer();
System.out.println("**************************************** main thread begin********************************");
//刚开始是抢占式的,take和put线程都可能先执行
for (int i = 0; i < 3; i++) {
new Thread(" put thread "+i) {
public void run() {
try {
//这里是匿名的内部类,所以要使用final变量
while(goonFlag[0].equals("true")){
bf.put(new Random().nextInt(100));
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}.start();
new Thread(" take thread "+i) {
public void run() {
try {
while(goonFlag[0].equals("true")){
try {
bf.take();
} catch (Exception e) {
e.printStackTrace();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();
}
try {
Thread.sleep(30000);
goonFlag[0]= "false";
} catch (InterruptedException e) {
e.printStackTrace();
}
}//main method
}
class BoundedBuffer {
final Lock lock = new ReentrantLock();// 锁对象
final Condition putCond = lock.newCondition();// 队列未满,写线程可以满足执行条件
final Condition takeCond = lock.newCondition();// 读线程条件
final List items = new ArrayList();// 缓存队列
public void put(Object x) throws InterruptedException {
lock.lock();
String threadName = Thread.currentThread().getName();
System.out.println("############### 【"+threadName+"】 get lock and sleep 500 ms ");
Thread.sleep(500);
try {
if (items.size()>=5){
System.out.println("############### 【"+threadName+"】 stack is full and await ");
takeCond.signalAll();//队列已经满了,读线程可以进行读取了
// 阻塞写线程
//一个线程被阻塞,从业务角度理解,它的使命已经完成
//如果要重新参与作业,就要重新参与线程的竞争
putCond.await();
}else{
if(!items.contains(x)){
items.add(x);// 赋值
System.out.println("############### 【"+threadName+"】 put: "+x);
System.out.println("############### 【"+threadName+"】 list length "+items.size()+", list content:"+items.toString());
takeCond.signalAll();//队列不为空,读线程可以进行读取了
}else{
System.out.println("############### 【"+threadName+"】 put same: "+x);
System.out.println("############### 【"+threadName+"】 list content:"+items.toString());
}
}
} finally {
System.out.println("############### 【"+threadName+"】 release the lock ");
lock.unlock();
}
}
public Object take() throws Exception {
lock.lock();
String threadName = Thread.currentThread().getName();
//int listSize = items.size();不能使用局部变量,因为如果使用,得到的可能是await之前的值
//await期间,该值可能已经被修改
System.out.println("**************** 【"+threadName+"】 get a lock and sleep 500ms ");
Thread.sleep(500);
try {
if (items.size() == 0){
System.out.println("**************** 【"+threadName+"】 stack is empty and await ");
putCond.signalAll();// 队列为空,就可以继续写入,也就是可以唤醒写线程
//当前线程调用了condition,被打上了相应的标签
//阻塞读线程。这里需要注意,被贴上了参与共享资源标签的线程在被唤醒后,
//可能会和还未打上标签的线程竞争。还有一种就是被打上了标签之后的多个线程同时竞争
takeCond.await();
return null;
}else{
Object x = items.get(items.size()-1);// 取值
System.out.println("**************** 【"+threadName+"】 get the value: "+x);
items.remove(x);
System.out.println("**************** 【"+threadName+"】 remain list : "+items.toString());
putCond.signalAll();// 队列未满,就可以继续写入,也就是可以唤醒写线程
return x;
}
}catch(Exception e){
e.printStackTrace();
return null;
}finally {
System.out.println("**************** 【"+threadName+"】 release the lock ");
lock.unlock();
}
}
}
运行结果:
**************************************** main thread begin********************************
############### 【 put thread 0】 get lock and sleep 500 ms
############### 【 put thread 0】 put: 66
############### 【 put thread 0】 list length 1, list content:[66]
############### 【 put thread 0】 release the lock
**************** 【 take thread 0】 get a lock and sleep 500ms
**************** 【 take thread 0】 get the value: 66
**************** 【 take thread 0】 remain list : []
**************** 【 take thread 0】 release the lock
############### 【 put thread 1】 get lock and sleep 500 ms
############### 【 put thread 1】 put: 57
############### 【 put thread 1】 list length 1, list content:[57]
############### 【 put thread 1】 release the lock
############### 【 put thread 1】 get lock and sleep 500 ms
############### 【 put thread 1】 put: 94
############### 【 put thread 1】 list length 2, list content:[57, 94]
############### 【 put thread 1】 release the lock
############### 【 put thread 2】 get lock and sleep 500 ms
############### 【 put thread 2】 put: 90
############### 【 put thread 2】 list length 3, list content:[57, 94, 90]
############### 【 put thread 2】 release the lock
############### 【 put thread 2】 get lock and sleep 500 ms
############### 【 put thread 2】 put: 23
############### 【 put thread 2】 list length 4, list content:[57, 94, 90, 23]
############### 【 put thread 2】 release the lock
**************** 【 take thread 1】 get a lock and sleep 500ms
**************** 【 take thread 1】 get the value: 23
**************** 【 take thread 1】 remain list : [57, 94, 90]
**************** 【 take thread 1】 release the lock
**************** 【 take thread 2】 get a lock and sleep 500ms
**************** 【 take thread 2】 get the value: 90
**************** 【 take thread 2】 remain list : [57, 94]
**************** 【 take thread 2】 release the lock
############### 【 put thread 0】 get lock and sleep 500 ms
############### 【 put thread 0】 put: 77
############### 【 put thread 0】 list length 3, list content:[57, 94, 77]
############### 【 put thread 0】 release the lock
**************** 【 take thread 0】 get a lock and sleep 500ms
**************** 【 take thread 0】 get the value: 77
**************** 【 take thread 0】 remain list : [57, 94]
**************** 【 take thread 0】 release the lock
############### 【 put thread 1】 get lock and sleep 500 ms
############### 【 put thread 1】 put: 74
############### 【 put thread 1】 list length 3, list content:[57, 94, 74]
############### 【 put thread 1】 release the lock
############### 【 put thread 2】 get lock and sleep 500 ms
############### 【 put thread 2】 put same: 94
############### 【 put thread 2】 list content:[57, 94, 74]
############### 【 put thread 2】 release the lock
############### 【 put thread 2】 get lock and sleep 500 ms
############### 【 put thread 2】 put: 28
############### 【 put thread 2】 list length 4, list content:[57, 94, 74, 28]
############### 【 put thread 2】 release the lock
**************** 【 take thread 1】 get a lock and sleep 500ms
**************** 【 take thread 1】 get the value: 28
**************** 【 take thread 1】 remain list : [57, 94, 74]
**************** 【 take thread 1】 release the lock
**************** 【 take thread 1】 get a lock and sleep 500ms
**************** 【 take thread 1】 get the value: 74
**************** 【 take thread 1】 remain list : [57, 94]
**************** 【 take thread 1】 release the lock
**************** 【 take thread 2】 get a lock and sleep 500ms
**************** 【 take thread 2】 get the value: 94
**************** 【 take thread 2】 remain list : [57]
**************** 【 take thread 2】 release the lock
############### 【 put thread 0】 get lock and sleep 500 ms
############### 【 put thread 0】 put: 15
############### 【 put thread 0】 list length 2, list content:[57, 15]
############### 【 put thread 0】 release the lock
**************** 【 take thread 0】 get a lock and sleep 500ms
**************** 【 take thread 0】 get the value: 15
**************** 【 take thread 0】 remain list : [57]
**************** 【 take thread 0】 release the lock
**************** 【 take thread 0】 get a lock and sleep 500ms
**************** 【 take thread 0】 get the value: 57
**************** 【 take thread 0】 remain list : []
**************** 【 take thread 0】 release the lock
**************** 【 take thread 0】 get a lock and sleep 500ms
**************** 【 take thread 0】 stack is empty and await
############### 【 put thread 1】 get lock and sleep 500 ms
############### 【 put thread 1】 put: 78
############### 【 put thread 1】 list length 1, list content:[78]
############### 【 put thread 1】 release the lock
############### 【 put thread 2】 get lock and sleep 500 ms
############### 【 put thread 2】 put: 70
############### 【 put thread 2】 list length 2, list content:[78, 70]
############### 【 put thread 2】 release the lock
############### 【 put thread 2】 get lock and sleep 500 ms
############### 【 put thread 2】 put: 40
############### 【 put thread 2】 list length 3, list content:[78, 70, 40]
############### 【 put thread 2】 release the lock
############### 【 put thread 2】 get lock and sleep 500 ms
############### 【 put thread 2】 put: 49
############### 【 put thread 2】 list length 4, list content:[78, 70, 40, 49]
############### 【 put thread 2】 release the lock
############### 【 put thread 2】 get lock and sleep 500 ms
############### 【 put thread 2】 put: 60
############### 【 put thread 2】 list length 5, list content:[78, 70, 40, 49, 60]
############### 【 put thread 2】 release the lock
############### 【 put thread 2】 get lock and sleep 500 ms
############### 【 put thread 2】 stack is full and await
**************** 【 take thread 1】 get a lock and sleep 500ms
**************** 【 take thread 1】 get the value: 60
**************** 【 take thread 1】 remain list : [78, 70, 40, 49]
**************** 【 take thread 1】 release the lock
**************** 【 take thread 1】 get a lock and sleep 500ms
**************** 【 take thread 1】 get the value: 49
**************** 【 take thread 1】 remain list : [78, 70, 40]
**************** 【 take thread 1】 release the lock
**************** 【 take thread 2】 get a lock and sleep 500ms
**************** 【 take thread 2】 get the value: 40
**************** 【 take thread 2】 remain list : [78, 70]
**************** 【 take thread 2】 release the lock
############### 【 put thread 0】 get lock and sleep 500 ms
############### 【 put thread 0】 put: 31
############### 【 put thread 0】 list length 3, list content:[78, 70, 31]
############### 【 put thread 0】 release the lock
**************** 【 take thread 0】 release the lock
**************** 【 take thread 0】 get a lock and sleep 500ms
**************** 【 take thread 0】 get the value: 31
**************** 【 take thread 0】 remain list : [78, 70]
**************** 【 take thread 0】 release the lock
**************** 【 take thread 0】 get a lock and sleep 500ms
**************** 【 take thread 0】 get the value: 70
**************** 【 take thread 0】 remain list : [78]
**************** 【 take thread 0】 release the lock
############### 【 put thread 1】 get lock and sleep 500 ms
############### 【 put thread 1】 put: 23
############### 【 put thread 1】 list length 2, list content:[78, 23]
############### 【 put thread 1】 release the lock
############### 【 put thread 1】 get lock and sleep 500 ms
############### 【 put thread 1】 put: 91
############### 【 put thread 1】 list length 3, list content:[78, 23, 91]
############### 【 put thread 1】 release the lock
############### 【 put thread 1】 get lock and sleep 500 ms
############### 【 put thread 1】 put: 57
############### 【 put thread 1】 list length 4, list content:[78, 23, 91, 57]
############### 【 put thread 1】 release the lock
############### 【 put thread 2】 release the lock
############### 【 put thread 2】 get lock and sleep 500 ms
############### 【 put thread 2】 put: 22
############### 【 put thread 2】 list length 5, list content:[78, 23, 91, 57, 22]
############### 【 put thread 2】 release the lock
############### 【 put thread 2】 get lock and sleep 500 ms
############### 【 put thread 2】 stack is full and await
**************** 【 take thread 1】 get a lock and sleep 500ms
**************** 【 take thread 1】 get the value: 22
**************** 【 take thread 1】 remain list : [78, 23, 91, 57]
**************** 【 take thread 1】 release the lock
**************** 【 take thread 2】 get a lock and sleep 500ms
**************** 【 take thread 2】 get the value: 57
**************** 【 take thread 2】 remain list : [78, 23, 91]
**************** 【 take thread 2】 release the lock
############### 【 put thread 0】 get lock and sleep 500 ms
############### 【 put thread 0】 put: 20
############### 【 put thread 0】 list length 4, list content:[78, 23, 91, 20]
############### 【 put thread 0】 release the lock
**************** 【 take thread 0】 get a lock and sleep 500ms
**************** 【 take thread 0】 get the value: 20
**************** 【 take thread 0】 remain list : [78, 23, 91]
**************** 【 take thread 0】 release the lock
**************** 【 take thread 0】 get a lock and sleep 500ms
**************** 【 take thread 0】 get the value: 91
**************** 【 take thread 0】 remain list : [78, 23]
**************** 【 take thread 0】 release the lock
**************** 【 take thread 0】 get a lock and sleep 500ms
**************** 【 take thread 0】 get the value: 23
**************** 【 take thread 0】 remain list : [78]
**************** 【 take thread 0】 release the lock
**************** 【 take thread 0】 get a lock and sleep 500ms
**************** 【 take thread 0】 get the value: 78
**************** 【 take thread 0】 remain list : []
**************** 【 take thread 0】 release the lock
**************** 【 take thread 0】 get a lock and sleep 500ms
**************** 【 take thread 0】 stack is empty and await
############### 【 put thread 1】 get lock and sleep 500 ms
############### 【 put thread 1】 put: 77
############### 【 put thread 1】 list length 1, list content:[77]
############### 【 put thread 1】 release the lock
############### 【 put thread 1】 get lock and sleep 500 ms
############### 【 put thread 1】 put: 5
############### 【 put thread 1】 list length 2, list content:[77, 5]
############### 【 put thread 1】 release the lock
############### 【 put thread 2】 release the lock
############### 【 put thread 2】 get lock and sleep 500 ms
############### 【 put thread 2】 put: 57
############### 【 put thread 2】 list length 3, list content:[77, 5, 57]
############### 【 put thread 2】 release the lock
############### 【 put thread 2】 get lock and sleep 500 ms
############### 【 put thread 2】 put: 27
############### 【 put thread 2】 list length 4, list content:[77, 5, 57, 27]
############### 【 put thread 2】 release the lock
############### 【 put thread 2】 get lock and sleep 500 ms
############### 【 put thread 2】 put: 32
############### 【 put thread 2】 list length 5, list content:[77, 5, 57, 27, 32]
############### 【 put thread 2】 release the lock
############### 【 put thread 2】 get lock and sleep 500 ms
############### 【 put thread 2】 stack is full and await
**************** 【 take thread 1】 get a lock and sleep 500ms
**************** 【 take thread 1】 get the value: 32
**************** 【 take thread 1】 remain list : [77, 5, 57, 27]
**************** 【 take thread 1】 release the lock
**************** 【 take thread 1】 get a lock and sleep 500ms
**************** 【 take thread 1】 get the value: 27
**************** 【 take thread 1】 remain list : [77, 5, 57]
**************** 【 take thread 1】 release the lock
**************** 【 take thread 1】 get a lock and sleep 500ms
**************** 【 take thread 1】 get the value: 57
**************** 【 take thread 1】 remain list : [77, 5]
**************** 【 take thread 1】 release the lock
**************** 【 take thread 2】 get a lock and sleep 500ms
**************** 【 take thread 2】 get the value: 5
**************** 【 take thread 2】 remain list : [77]
**************** 【 take thread 2】 release the lock
**************** 【 take thread 2】 get a lock and sleep 500ms
**************** 【 take thread 2】 get the value: 77
**************** 【 take thread 2】 remain list : []
**************** 【 take thread 2】 release the lock
############### 【 put thread 0】 get lock and sleep 500 ms
############### 【 put thread 0】 put: 28
############### 【 put thread 0】 list length 1, list content:[28]
############### 【 put thread 0】 release the lock
**************** 【 take thread 0】 release the lock
**************** 【 take thread 0】 get a lock and sleep 500ms
**************** 【 take thread 0】 get the value: 28
**************** 【 take thread 0】 remain list : []
**************** 【 take thread 0】 release the lock
**************** 【 take thread 0】 get a lock and sleep 500ms
**************** 【 take thread 0】 stack is empty and await
############### 【 put thread 1】 get lock and sleep 500 ms
############### 【 put thread 1】 put: 92
############### 【 put thread 1】 list length 1, list content:[92]
############### 【 put thread 1】 release the lock
############### 【 put thread 2】 release the lock
**************** 【 take thread 1】 get a lock and sleep 500ms
**************** 【 take thread 1】 get the value: 92
**************** 【 take thread 1】 remain list : []
**************** 【 take thread 1】 release the lock
**************** 【 take thread 2】 get a lock and sleep 500ms
**************** 【 take thread 2】 stack is empty and await
############### 【 put thread 0】 get lock and sleep 500 ms
############### 【 put thread 0】 put: 20
############### 【 put thread 0】 list length 1, list content:[20]
############### 【 put thread 0】 release the lock
**************** 【 take thread 0】 release the lock
**************** 【 take thread 2】 release the lock