《java并发编程实战》基础构建模块(六)
2014-11-15 10:03
218 查看
5.5.3 信号量
计数信号量用来控制同时访问某个资源的操作数量,或者同时执行某个指定操作的数量。另外还可以用来实现某种资源池,或者对容器施加边界。
例如:
package com.imeiren.cache;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
public class BoundedHashSet<T> {
private final Set<T> set;
private final Semaphore sem;
public BoundedHashSet(int bound) {
this.set = Collections.synchronizedSet(new HashSet<T>());
sem = new Semaphore(bound);
}
public boolean remove(Object o) {
boolean wasRemoved = set.remove(o);
if (wasRemoved) {
sem.release();
}
return wasRemoved;
}
public boolean add(T o) throws InterruptedException {
SimpleDateFormat formater = new SimpleDateFormat("hh:MM:ss");
System.out.println(formater.format(Calendar.getInstance().getTime())
+ " " + Thread.currentThread() + " enter add method");
sem.acquire();
System.out.println(formater.format(Calendar.getInstance().getTime())
+ " " + Thread.currentThread() + " finished waiting status");
boolean wasAdded = false;
try {
Thread.sleep(2000);
wasAdded = set.add(o);
return wasAdded;
} finally {
if (!wasAdded) {
sem.release();
}
}
}
public static void main(String[] args) {
final BoundedHashSet<String> set = new BoundedHashSet<String>(2);
ExecutorService executorService = Executors.newCachedThreadPool();
for (int i = 0; i < 5; i++) {
executorService.execute(new Runnable() {
@Override
public void run() {
try {
set.add("Hello World!");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
executorService.shutdown();
}
}
某次执行的输出结果:
09:11:13 Thread[pool-1-thread-3,5,main] enter add method
09:11:13 Thread[pool-1-thread-5,5,main] enter add method
09:11:13 Thread[pool-1-thread-3,5,main] finished waiting status
09:11:13 Thread[pool-1-thread-1,5,main] enter add method
09:11:13 Thread[pool-1-thread-4,5,main] enter add method
09:11:13 Thread[pool-1-thread-2,5,main] enter add method
09:11:13 Thread[pool-1-thread-5,5,main] finished waiting status
09:11:15 Thread[pool-1-thread-1,5,main] finished waiting status
09:11:17 Thread[pool-1-thread-4,5,main] finished waiting status
09:11:19 Thread[pool-1-thread-2,5,main] finished waiting status
我们设置容器边界为2,用5个线程同时访问容器。我们看到在13秒时5个线程同时进入add方法,线程3、5不需要等待,在13秒时就结束等待状态,而之后其他三个线程分别在15、17、19秒的时候结束等待状态。
计数信号量用来控制同时访问某个资源的操作数量,或者同时执行某个指定操作的数量。另外还可以用来实现某种资源池,或者对容器施加边界。
例如:
package com.imeiren.cache;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
public class BoundedHashSet<T> {
private final Set<T> set;
private final Semaphore sem;
public BoundedHashSet(int bound) {
this.set = Collections.synchronizedSet(new HashSet<T>());
sem = new Semaphore(bound);
}
public boolean remove(Object o) {
boolean wasRemoved = set.remove(o);
if (wasRemoved) {
sem.release();
}
return wasRemoved;
}
public boolean add(T o) throws InterruptedException {
SimpleDateFormat formater = new SimpleDateFormat("hh:MM:ss");
System.out.println(formater.format(Calendar.getInstance().getTime())
+ " " + Thread.currentThread() + " enter add method");
sem.acquire();
System.out.println(formater.format(Calendar.getInstance().getTime())
+ " " + Thread.currentThread() + " finished waiting status");
boolean wasAdded = false;
try {
Thread.sleep(2000);
wasAdded = set.add(o);
return wasAdded;
} finally {
if (!wasAdded) {
sem.release();
}
}
}
public static void main(String[] args) {
final BoundedHashSet<String> set = new BoundedHashSet<String>(2);
ExecutorService executorService = Executors.newCachedThreadPool();
for (int i = 0; i < 5; i++) {
executorService.execute(new Runnable() {
@Override
public void run() {
try {
set.add("Hello World!");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
executorService.shutdown();
}
}
某次执行的输出结果:
09:11:13 Thread[pool-1-thread-3,5,main] enter add method
09:11:13 Thread[pool-1-thread-5,5,main] enter add method
09:11:13 Thread[pool-1-thread-3,5,main] finished waiting status
09:11:13 Thread[pool-1-thread-1,5,main] enter add method
09:11:13 Thread[pool-1-thread-4,5,main] enter add method
09:11:13 Thread[pool-1-thread-2,5,main] enter add method
09:11:13 Thread[pool-1-thread-5,5,main] finished waiting status
09:11:15 Thread[pool-1-thread-1,5,main] finished waiting status
09:11:17 Thread[pool-1-thread-4,5,main] finished waiting status
09:11:19 Thread[pool-1-thread-2,5,main] finished waiting status
我们设置容器边界为2,用5个线程同时访问容器。我们看到在13秒时5个线程同时进入add方法,线程3、5不需要等待,在13秒时就结束等待状态,而之后其他三个线程分别在15、17、19秒的时候结束等待状态。
相关文章推荐
- 《Java并发编程实战》读书笔记-第5章 基础构建模块
- Java并发编程实战(二)基础构建模块
- 《java并发编程实战》基础构建模块(七)
- java并发编程实战-基础构建模块1
- 《java并发编程实战》基础构建模块(四)
- 《java并发编程实战》基础构建模块(三)
- java并发编程实战-基础构建模块3
- java并发编程实战:基础构建模块笔记
- 《java并发编程实战》基础构建模块(五)
- Java并发编程实战 - 第5章 基础构建模块
- Java并发编程实战(学习笔记四 第五章 基础构建模块 上)
- 《java并发编程实战》基础构建模块(二)
- 《java并发编程实战》基础构建模块(一)
- 《Java并发编程实战》 阅读笔记 5. 基础构建模块
- Java并发编程实战笔记(4)-基础构建模块
- java并发编程实战-基础构建模块2
- 《java并发编程实战》读书笔记4--基础构建模块,java中的同步容器类&并发容器类&同步工具类,消费者模式
- java并发编程实战学习(3)--基础构建模块
- Java并发编程基础构建模块(02)——并发容器
- Java并发编程基础构建模块(06)——高效缓存总结示例