Guava并发(1)——Monitor的使用

一、说明

Monitor就像java本土的synchronized, ReentrantLock一样,每次只运行一个线程占用,且可重占用,每一次占用会对应一次退出占用。

Monitor.enter //进入Monitor块,将阻塞其他线程知道Monitor.leave
Monitor.enterWhen  //进入Monitor块,将阻塞其他线程知道Monitor.leave

Monitor.tryEnter //尝试进入Monitor块,true表示可以进入, false表示不能,并且不会一直阻塞
Monitor.tryEnterIf //根据条件尝试进入Monitor块


Monitor.Guard是造成线程阻塞的条件,与 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

四、总结

 略。


你可能感兴趣的:(guava,JAVA并发包)