Semaphore
- 正常的锁在任何时刻都只允许一个任务访问一项资源,而计数信号量允许n个任务同时访问这个资源。还可以将信号量看作是在向外分发使用资源的“许可证”,尽管实际上没有使用任何许可证对象。
- 对象池的概念,管理者数量有限的对象,当要使用对象时可以迁出它们,而在用户使用完毕时,可以将它们迁回。
package com21concurrent;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Semaphore;
public class Pool<T> {
private int size;
private List<T> items=new ArrayList<>();
private volatile boolean[] checkedOut;
private Semaphore available;
public Pool(Class<T> classObject,int size) {
this.size = size;
checkedOut=new boolean[size];
available=new Semaphore(size,true);
for (int i = 0; i < size; i++) {
try{
items.add(classObject.newInstance());
}catch (Exception e){
throw new RuntimeException(e);
}
}
}
public T checkOut() throws InterruptedException{
available.acquire();
return getItem();
}
public void checkIn(T x){
if(releaseItem(x)){
available.release();
}
}
private synchronized T getItem(){
for (int i = 0; i <size ; i++) {
if(!checkedOut[i]){
checkedOut[i]=true;
return items.get(i);
}
}
return null;
}
private synchronized boolean releaseItem(T item){
int index=items.indexOf(item);
if(index==-1) return false;
if(checkedOut[index]){
checkedOut[index]=false;
return true;
}
return false;
}
}
package com21concurrent;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
/**
* Created by Panda on 2018/6/1.
*/
class Fat{
private volatile double d;
private static int counter=0;
private final int id=counter++;
public Fat() {
for (int i = 0; i <10000 ; i++) {
d+=(Math.PI+Math.E)/(double)i;
}
}
public void operation(){
System.out.println(this);
}
public String toString(){
return "Fat id:"+id;
}
}
class CheckoutTask<T> implements Runnable{
private static int counter=0;
private final int id=counter++;
private Pool<T> pool;
public CheckoutTask(Pool<T> pool) {
this.pool = pool;
}
@Override
public void run() {
try{
T item=pool.checkOut();
System.out.println(this+"checked out "+item);
TimeUnit.SECONDS.sleep(1);
System.out.println(this+"checking in "+item);
pool.checkIn(item);
}catch (InterruptedException e){
}
}
public String toString(){
return "CheckoutTask "+id+" ";
}
}
public class SemaphoreDemo {
final static int SIZE=25;
public static void main(String[] args) throws Exception {
final Pool<Fat> pool= new Pool<>(Fat.class,SIZE);
ExecutorService executorService = Executors.newCachedThreadPool();
for (int i = 0; i < SIZE; i++) {
executorService.execute(new CheckoutTask<Fat>(pool));
}
System.out.println("All checkoutTasks created");
List<Fat> list = new ArrayList<>();
for (int i = 0; i <SIZE ; i++) {
Fat fat = pool.checkOut();
System.out.println(i+":main() thread checked out");
fat.operation();
list.add(fat);
}
Future<?> blocked=executorService.submit(new Runnable() {
@Override
public void run() {
try{
pool.checkOut();
}catch (InterruptedException e){
System.out.println("checkOut() Interrupted");
}
}
});
TimeUnit.SECONDS.sleep(2);
blocked.cancel(true);
System.out.println("checking in objects in"+list);
for(Fat fat:list){
pool.checkIn(fat);
}
for(Fat fat:list){
pool.checkIn(fat);
}
executorService.shutdownNow();
}
}