SemaphoreDemo.java
一个资源池Pool,可以由多个线程检出和检入其中的资源,由Semaphore控制同步问题,由数组来记录每个资源的检出/检入状态
CheckoutTask这个线程,启动多个,负责检入检出资源。
资源类Fat,有比较复杂的计算
同时在main()方法中对资源进行了检出和检入操作
package com.test.concurrent;
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.Semaphore;
import java.util.concurrent.TimeUnit;
public class SemaphoreDemo {
static final int SIZE=25;
public static void main(String[] args) throws InterruptedException {
// TODO Auto-generated method stub
final Pool<Fat> pool=new Pool(SIZE,Fat.class);
ExecutorService exec=Executors.newCachedThreadPool();
for(int i=0;i<SIZE;i++){
exec.execute(new CheckoutTask(pool));
}
System.out.println("All checkoutTask created!!!");
List<Fat> list=new ArrayList<Fat>();
for(int i=0;i<SIZE;i++){
Fat f=pool.checkOut();
System.out.println(i+" : main() thread check out");
f.operation();
list.add(f);
}
Future<?> blocked=exec.submit(new Runnable(){
public void run(){
try {
pool.checkOut();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
System.out.println("Checkout Interrupted!!!!!!!!!!!!");
e.printStackTrace();
}
}
});
TimeUnit.SECONDS.sleep(2);
blocked.cancel(true);
System.out.println("-------------Checking in objects in "+list);
for(int i=0;i<SIZE;i++){
Fat item=list.get(i);
pool.checkIn(item);
}
for(Fat f:list){
pool.checkIn(f);
exec.shutdown();
}
}
}
class Pool<T>{
private int size;
private Semaphore available;
private volatile boolean checkOut[];
private List<T> items=new ArrayList<T>();
public Pool(int size, Class<T> objectClass){
this.size=size;
available=new Semaphore(size,true);
checkOut=new boolean[size];
for(int i=0;i<size;i++){
try {
items.add(objectClass.newInstance());
} catch (InstantiationException | IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public T checkOut() throws InterruptedException{
available.acquire();
return getItem();
}
public void checkIn(T t){
if(releaseItem(t))
available.release();
}
private synchronized T getItem(){
for(int i=0;i<size;i++){
if(!checkOut[i]){
checkOut[i]=true;
return (T)items.get(i);
}
}
return null;
}
private synchronized boolean releaseItem(T item){
int index=items.indexOf(item);
if(index<0){
return false;
}
if(checkOut[index]){
checkOut[index]=false;
return true;
}
return false;
}
}
class Fat{
private volatile double d; //prevent optimization
private static int counter=0;
private final int id=counter++;
public Fat(){
for(int i=0;i<10000;i++){
d+=(Math.PI+Math.E);
}
}
public String toString(){
return "Fat id: "+id+" D:"+d;
}
public void operation(){
System.out.println(this);
}
}
class CheckoutTask<T> implements Runnable{
private static int counter=0;
private final int id=counter++;
Pool<T> pool;
public CheckoutTask(Pool<T> pool){
this.pool=pool;
}
@Override
public void run(){
try {
T item=pool.checkOut();
System.out.println(this+" check out "+item);
TimeUnit.SECONDS.sleep(1);
System.out.println(this+" check in "+item);
pool.checkIn(item);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public String toString(){
return "CheckoutTask id:"+id+" ";
}
}
输出为:
All checkoutTask created!!!
0 : main() thread check out
CheckoutTask id:9 check out Fat id: 9 D:58598.74482048422
CheckoutTask id:4 check out Fat id: 4 D:58598.74482048422
CheckoutTask id:23 check out Fat id: 24 D:58598.74482048422
CheckoutTask id:19 check out Fat id: 17 D:58598.74482048422
CheckoutTask id:0 check out Fat id: 0 D:58598.74482048422
CheckoutTask id:16 check out Fat id: 16 D:58598.74482048422
CheckoutTask id:20 check out Fat id: 18 D:58598.74482048422
CheckoutTask id:6 check out Fat id: 6 D:58598.74482048422
CheckoutTask id:11 check out Fat id: 11 D:58598.74482048422
CheckoutTask id:8 check out Fat id: 8 D:58598.74482048422
CheckoutTask id:7 check out Fat id: 7 D:58598.74482048422
CheckoutTask id:10 check out Fat id: 10 D:58598.74482048422
CheckoutTask id:21 check out Fat id: 22 D:58598.74482048422
CheckoutTask id:22 check out Fat id: 19 D:58598.74482048422
CheckoutTask id:17 check out Fat id: 21 D:58598.74482048422
CheckoutTask id:1 check out Fat id: 1 D:58598.74482048422
CheckoutTask id:12 check out Fat id: 15 D:58598.74482048422
CheckoutTask id:18 check out Fat id: 20 D:58598.74482048422
CheckoutTask id:13 check out Fat id: 12 D:58598.74482048422
CheckoutTask id:2 check out Fat id: 2 D:58598.74482048422
CheckoutTask id:14 check out Fat id: 13 D:58598.74482048422
CheckoutTask id:15 check out Fat id: 14 D:58598.74482048422
Fat id: 23 D:58598.74482048422
CheckoutTask id:3 check out Fat id: 3 D:58598.74482048422
CheckoutTask id:5 check out Fat id: 5 D:58598.74482048422
CheckoutTask id:9 check in Fat id: 9 D:58598.74482048422
CheckoutTask id:20 check in Fat id: 18 D:58598.74482048422
CheckoutTask id:16 check in Fat id: 16 D:58598.74482048422
CheckoutTask id:0 check in Fat id: 0 D:58598.74482048422
1 : main() thread check out
Fat id: 16 D:58598.74482048422
2 : main() thread check out
Fat id: 0 D:58598.74482048422
3 : main() thread check out
Fat id: 18 D:58598.74482048422
CheckoutTask id:4 check in Fat id: 4 D:58598.74482048422
CheckoutTask id:23 check in Fat id: 24 D:58598.74482048422
4 : main() thread check out
Fat id: 4 D:58598.74482048422
5 : main() thread check out
Fat id: 24 D:58598.74482048422
CheckoutTask id:12 check in Fat id: 15 D:58598.74482048422
CheckoutTask id:8 check in Fat id: 8 D:58598.74482048422
6 : main() thread check out
Fat id: 15 D:58598.74482048422
7 : main() thread check out
Fat id: 8 D:58598.74482048422
CheckoutTask id:19 check in Fat id: 17 D:58598.74482048422
CheckoutTask id:24 check out Fat id: 9 D:58598.74482048422
8 : main() thread check out
Fat id: 17 D:58598.74482048422
CheckoutTask id:17 check in Fat id: 21 D:58598.74482048422
9 : main() thread check out
Fat id: 21 D:58598.74482048422
CheckoutTask id:14 check in Fat id: 13 D:58598.74482048422
10 : main() thread check out
Fat id: 13 D:58598.74482048422
CheckoutTask id:11 check in Fat id: 11 D:58598.74482048422
11 : main() thread check out
Fat id: 11 D:58598.74482048422
CheckoutTask id:6 check in Fat id: 6 D:58598.74482048422
12 : main() thread check out
Fat id: 6 D:58598.74482048422
CheckoutTask id:5 check in Fat id: 5 D:58598.74482048422
13 : main() thread check out
Fat id: 5 D:58598.74482048422
CheckoutTask id:7 check in Fat id: 7 D:58598.74482048422
14 : main() thread check out
Fat id: 7 D:58598.74482048422
CheckoutTask id:10 check in Fat id: 10 D:58598.74482048422
15 : main() thread check out
Fat id: 10 D:58598.74482048422
CheckoutTask id:21 check in Fat id: 22 D:58598.74482048422
16 : main() thread check out
Fat id: 22 D:58598.74482048422
CheckoutTask id:22 check in Fat id: 19 D:58598.74482048422
17 : main() thread check out
Fat id: 19 D:58598.74482048422
CheckoutTask id:1 check in Fat id: 1 D:58598.74482048422
18 : main() thread check out
Fat id: 1 D:58598.74482048422
CheckoutTask id:18 check in Fat id: 20 D:58598.74482048422
19 : main() thread check out
Fat id: 20 D:58598.74482048422
CheckoutTask id:13 check in Fat id: 12 D:58598.74482048422
20 : main() thread check out
Fat id: 12 D:58598.74482048422
CheckoutTask id:2 check in Fat id: 2 D:58598.74482048422
21 : main() thread check out
Fat id: 2 D:58598.74482048422
CheckoutTask id:15 check in Fat id: 14 D:58598.74482048422
22 : main() thread check out
Fat id: 14 D:58598.74482048422
CheckoutTask id:3 check in Fat id: 3 D:58598.74482048422
23 : main() thread check out
Fat id: 3 D:58598.74482048422
CheckoutTask id:24 check in Fat id: 9 D:58598.74482048422
24 : main() thread check out
Fat id: 9 D:58598.74482048422
Checkout Interrupted!!!!!!!!!!!!
-------------Checking in objects in [Fat id: 23 D:58598.74482048422, Fat id: 16 D:58598.74482048422, Fat id: 0 D:58598.74482048422, Fat id: 18 D:58598.74482048422, Fat id: 4 D:58598.74482048422, Fat id: 24 D:58598.74482048422, Fat id: 15 D:58598.74482048422, Fat id: 8 D:58598.74482048422, Fat id: 17 D:58598.74482048422, Fat id: 21 D:58598.74482048422, Fat id: 13 D:58598.74482048422, Fat id: 11 D:58598.74482048422, Fat id: 6 D:58598.74482048422, Fat id: 5 D:58598.74482048422, Fat id: 7 D:58598.74482048422, Fat id: 10 D:58598.74482048422, Fat id: 22 D:58598.74482048422, Fat id: 19 D:58598.74482048422, Fat id: 1 D:58598.74482048422, Fat id: 20 D:58598.74482048422, Fat id: 12 D:58598.74482048422, Fat id: 2 D:58598.74482048422, Fat id: 14 D:58598.74482048422, Fat id: 3 D:58598.74482048422, Fat id: 9 D:58598.74482048422]
java.lang.InterruptedException
at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedInterruptibly(Unknown Source)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(Unknown Source)
at java.util.concurrent.Semaphore.acquire(Unknown Source)
at com.test.concurrent.Pool.checkOut(SemaphoreDemo.java:73)
at com.test.concurrent.SemaphoreDemo$1.run(SemaphoreDemo.java:31)
at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
at java.util.concurrent.FutureTask.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)