一、Semaphore
信号量,用于流量控制,同时允计N个线程获访问
同时允许3个线程去竞争打印机:
public class PrintQueue {
private boolean freePrinters[];
private Lock lockPrinters;
//2. 声明一个对象为Semaphore,称它为semaphore。
private final Semaphore semaphore;
// 实现类的构造函数并初始能保护print quere的访问的semaphore对象的值。
public PrintQueue(){
//设置共享资源个数为3个
this.semaphore=new Semaphore(3);
freePrinters=new boolean[3];
for(int i=0;i<freePrinters.length;i++){
freePrinters[i]=true;
}
lockPrinters = new ReentrantLock();
}
public void printJob(Object document){
try{
semaphore.acquire();
//获取空闲打印机序号
int assignedPrinter=getPrinter();
long duration=(long)(Math.random()*10);
System.out.printf("%s: PrintQueue: Printing a Job during %d seconds\n",Thread.currentThread().getName(),duration);
Thread.sleep(duration);
//打印机用完后,标记为空闲
freePrinters[assignedPrinter]=true;
System.out.println("this assignedprinter is "+ assignedPrinter);
}catch (InterruptedException e){
}finally {
semaphore.release();
}
}
public int getPrinter(){
int ret = -1;
try{
lockPrinters.lock();
for(int i=0;i<freePrinters.length;i++){
if(freePrinters[i]){
ret = i;
freePrinters[i]=false;
break;
}
}
}catch (Exception e){
}finally {
lockPrinters.unlock();
}
return ret;
}
}
1、new Semaphore(3)
构造方法,初始化status为可同时获取锁的个数
2、semaphore.acquire()
自旋 cas方法修改state-1,直到修成功 或 state<0
如果小于0 那么阻塞
否则获取锁成功
3、semaphore.release()
自旋cas方式将state+1 直到成功
修改成功后 唤醒阻塞的线程
二、callable
可以返回线程执行结果,通过feartrueTask得到执行结果
callable,runnable ,futrue,futrueTask联系
callable,runnable 分别是接口,一个有返回值,一个没有返回值
futrue是一个接口,定义了对runnable callable任务一系列操作
:取消、查询是否完成、获取结果、设置结果操作
RunnableFuture接口:继承runnable ,futrue
FutureTask实现类,实现RunnableFuture接口
定义了以runnable ,callable为参数的构造方法(最终runnable会被转成callable执行). 所以通过FutureTask.get()可以拿到callable的返回值
FutureTask.get()这个方法是一阻塞超时方法,在线程返回结果前会阻塞,若超过了超时时间也会返回