计数信号量用来控制同时访问某个特定资源的操作数量或者同时执行某个指定操作的数量。可以用来实现资源池或者给容器加边界。
Semaphore用来实现有边界的容器
public class SemaphoreTest {
public static void main(String[] args) {
BoundedHashSet<Integer> bhs = new BoundedHashSet<Integer>(10);
for (int i = 0; i < 100; i++) {
if (bhs.add(i))
System.out.println("成功添加" + i);
else
System.out.println("添加失败" + i);
}
}
/**
* 有界容器
*
* @author hasee
*
* @param <T>
*/
static class BoundedHashSet<T> {
private final Set<T> set;
private final Semaphore sp;
public BoundedHashSet(int bound) {
this.set = Collections.synchronizedSet(new HashSet<T>());
this.sp = new Semaphore(bound);
}
public boolean add(T t) {
if (!sp.tryAcquire())
return false;
boolean isAdded = false;
try {
isAdded = set.add(t);
return isAdded;
} finally {
if (!isAdded)
sp.release();
}
}
public boolean remove(T t) {
boolean isRemoved = set.remove(t);
if (isRemoved)
sp.release();
return isRemoved;
}
}
}
Semaphore用来实现资源池
public class SemaphoreTest2 {
public static void main(String[] args) {
final ConnectionPool pool = new ConnectionPool(5);
for (int i = 0; i < 10; i++) {
Thread t = new Thread() {
@Override
public void run() {
try {
Connection conn = pool.getConnection();
Thread.sleep(1000);
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
};
t.start();
}
}
static class ConnectionPool {
private final Map<Integer, Connection> conns;
private final boolean[] states;
private final Semaphore sp;
private final int size;
public ConnectionPool(int size) {
this.size = size;
sp = new Semaphore(size);
conns = new HashMap<Integer, Connection>(size);
states = new boolean[size];
for (int i = 0; i < size; i++) {
conns.put(i, new Connection(i));
states[i] = true;
}
}
/**
* 阻塞式获取连接对象
*
* @return
* @throws Exception
*/
public Connection getConnection() throws Exception {
try {
sp.acquire();
} catch (InterruptedException e) {
return null;
}
synchronized (conns) {
for (int i = 0; i < size; i++)
if (states[i]) {
System.out.println(Thread.currentThread().getName() + "获取Connection对象:conn---" + i);
states[i] = false;
return conns.get(i);
}
}
throw new Exception(ConnectionPool.class.getName() + "逻辑有漏洞!!");
}
class Connection {
final int token;
public Connection(int token) {
this.token = token;
}
public synchronized void close() {
// TODO 释放资源
System.out.println(Thread.currentThread().getName() + "释放Connection对象:conn--" + token);
states[token] = true;
sp.release();
}
}
}
}