一、说明
Monitor就像java本土的synchronized, ReentrantLock一样,每次只运行一个线程占用,且可重占用,每一次占用会对应一次退出占用。
Monitor.enter //进入Monitor块,将阻塞其他线程知道Monitor.leave
Monitor.enterWhen //进入Monitor块,将阻塞其他线程知道Monitor.leave
Monitor.tryEnter //尝试进入Monitor块,true表示可以进入, false表示不能,并且不会一直阻塞
Monitor.tryEnterIf //根据条件尝试进入Monitor块
Monitor.Guard listBelowCapacity = new
Monitor.Guard(monitor) {
@Override
public boolean isSatisfied() {
。。。。。
}
};
二、代码
package com.wll.guava.concurrent;
import com.google.common.util.concurrent.Monitor;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* Monitor类语义和 synchronized 或者 ReentrantLocks是一样的, 只允许一个线程进入
*/
public class MonitorExample {
private static final int MAX_SIZE = 10;
private Monitor monitor = new Monitor();
private List list = new ArrayList();
Monitor.Guard listBelowCapacity = new
Monitor.Guard(monitor) {
@Override
public boolean isSatisfied() {
return list.size() < MAX_SIZE;
}
};
public void addToListWait(String item) throws InterruptedException {
// 超过MAX_SIZE, 会锁死(阻塞)
this.monitor.enterWhen(listBelowCapacity);
try {
list.add(item);
System.out.println("添加元素[" + item + "]成功,当前List.size=" + list.size() + "~");
} finally { // 确保线程会退出Monitor锁
monitor.leave();
}
}
public void addToListSkipWait(String item) throws InterruptedException {
// 超过MAX_SIZE, 会锁死
//this.monitor.enterWhen(listBelowCapacity);
// 超过返回false 不会锁死
Boolean isOK = monitor.tryEnterIf(listBelowCapacity);
System.out.println("Thread[" + Thread.currentThread().getName() + "] item=" + item + ",获取令牌:isOK=" + isOK);
if (isOK) {
try {
list.add(item);
System.out.println("添加元素[" + item + "]成功,当前List.size=" + list.size() + "~");
} finally { // 确保线程会退出Monitor锁
monitor.leave();
}
}
}
public static void main(String[] args) {
final MonitorExample monitorDemo = new MonitorExample();
for (int i = 0; i < 5; i++) {
new Thread() {
public void run() {
for (int count = 0; count < 6; count++) {
try {
// monitorDemo.addToListWait(count + "------------------>" + Thread.currentThread().getName());
monitorDemo.addToListSkipWait(count + "------------------>" + Thread.currentThread().getName());
Thread.sleep(100L);
} catch (Exception e) {
System.out.println(e);
}
}
}
}.start();
}
// 等待所有线程执行完毕
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("---------------------------- 长长的分割线 ---------------------------");
Iterator iteratorStringList = monitorDemo.list.iterator();
while (iteratorStringList.hasNext()) {
System.out.println(iteratorStringList.next());
}
}
}
三、执行结果
Connected to the target VM, address: '127.0.0.1:61207', transport: 'socket'
Thread[Thread-2] item=0------------------>Thread-2,获取令牌:isOK=false
Thread[Thread-1] item=0------------------>Thread-1,获取令牌:isOK=false
Thread[Thread-4] item=0------------------>Thread-4,获取令牌:isOK=false
Thread[Thread-0] item=0------------------>Thread-0,获取令牌:isOK=false
Thread[Thread-3] item=0------------------>Thread-3,获取令牌:isOK=true
添加元素[0------------------>Thread-3]成功,当前List.size=1~
Thread[Thread-3] item=1------------------>Thread-3,获取令牌:isOK=true
添加元素[1------------------>Thread-3]成功,当前List.size=2~
Thread[Thread-2] item=1------------------>Thread-2,获取令牌:isOK=true
Thread[Thread-0] item=1------------------>Thread-0,获取令牌:isOK=false
Thread[Thread-4] item=1------------------>Thread-4,获取令牌:isOK=false
添加元素[1------------------>Thread-2]成功,当前List.size=3~
Thread[Thread-1] item=1------------------>Thread-1,获取令牌:isOK=false
Thread[Thread-2] item=2------------------>Thread-2,获取令牌:isOK=true
添加元素[2------------------>Thread-2]成功,当前List.size=4~
Thread[Thread-0] item=2------------------>Thread-0,获取令牌:isOK=true
添加元素[2------------------>Thread-0]成功,当前List.size=5~
Thread[Thread-4] item=2------------------>Thread-4,获取令牌:isOK=true
添加元素[2------------------>Thread-4]成功,当前List.size=6~
Thread[Thread-1] item=2------------------>Thread-1,获取令牌:isOK=true
添加元素[2------------------>Thread-1]成功,当前List.size=7~
Thread[Thread-3] item=2------------------>Thread-3,获取令牌:isOK=true
添加元素[2------------------>Thread-3]成功,当前List.size=8~
Thread[Thread-3] item=3------------------>Thread-3,获取令牌:isOK=true
添加元素[3------------------>Thread-3]成功,当前List.size=9~
Thread[Thread-2] item=3------------------>Thread-2,获取令牌:isOK=false
Thread[Thread-0] item=3------------------>Thread-0,获取令牌:isOK=true
添加元素[3------------------>Thread-0]成功,当前List.size=10~
Thread[Thread-1] item=3------------------>Thread-1,获取令牌:isOK=false
Thread[Thread-4] item=3------------------>Thread-4,获取令牌:isOK=false
Thread[Thread-2] item=4------------------>Thread-2,获取令牌:isOK=false
Thread[Thread-1] item=4------------------>Thread-1,获取令牌:isOK=false
Thread[Thread-4] item=4------------------>Thread-4,获取令牌:isOK=false
Thread[Thread-3] item=4------------------>Thread-3,获取令牌:isOK=false
Thread[Thread-0] item=4------------------>Thread-0,获取令牌:isOK=false
Thread[Thread-3] item=5------------------>Thread-3,获取令牌:isOK=false
Thread[Thread-2] item=5------------------>Thread-2,获取令牌:isOK=false
Thread[Thread-4] item=5------------------>Thread-4,获取令牌:isOK=false
Thread[Thread-0] item=5------------------>Thread-0,获取令牌:isOK=false
Thread[Thread-1] item=5------------------>Thread-1,获取令牌:isOK=false
---------------------------- 长长的分割线 ---------------------------
0------------------>Thread-3
1------------------>Thread-3
1------------------>Thread-2
2------------------>Thread-2
2------------------>Thread-0
2------------------>Thread-4
2------------------>Thread-1
2------------------>Thread-3
3------------------>Thread-3
3------------------>Thread-0
Disconnected from the target VM, address: '127.0.0.1:61207', transport: 'socket'
Process finished with exit code 0
四、总结
略。