原先多线程并发编程的学习笔记和代码整理一下贴上来。
---------------------------------
信号量Semaphore
根据JDK文档描述:
一个计数信号量。从概念上讲,信号量维护了一个许可集。如有必要,在许可可用前会阻塞每一个 acquire(),然后再获取该许可。每个 release() 添加一个许可,从而可能释放一个正在阻塞的获取者。但是,不使用实际的许可对象,Semaphore 只对可用许可的号码进行计数,并采取相应的行动。
个人理解为定义一个信号量同时指定它的许可数量,acquire时许可+1,release时许可-1。如果到达最大许可数时,后面的线程会阻塞。
一个简单的示例:
定义一个打印资源id的任务。该任务在运行前先获取信号量的一个许可,运行完后会释放该许可。
class ResourceInfo implements Runnable{
private final int resId;
private Semaphore semaphore;
public ResourceInfo(int rid,Semaphore semp){
this.semaphore=semp;
resId=rid;
}
@Override
public void run() {
try{
semaphore.acquire();
System.out.println("resId:"+resId);
Thread.sleep((long) (Math.random() * 10000));
semaphore.release();
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
然后使用信号量:
ExecutorService exec = Executors.newCachedThreadPool();
Semaphore semap=new Semaphore(10);
for(int i=0;i<20;i++){
exec.execute(new ResourceInfo(i, semap));
}
exec.shutdown();
这里定义了一个信号量,最多允许10个任务获取许可,然后一次启动20个任务。运行结果如下:
resId:0
resId:2
resId:1
resId:3
resId:5
resId:6
resId:4
resId:7
resId:8
resId:9
resId:10
resId:11
resId:13
resId:12
resId:14
resId:16
resId:15
resId:17
resId:19
resId:18
前10个任务获取到许可后,后面的10个任务会阻塞,直到前面的任务释放许可。这里我们修改一下:
Semaphore semap=new Semaphore(10,true);
指定公平设置(默认为false):如果此信号量保证在争用时按先进先出的顺序授予许可,则为 true;否则为 false。再运行一下看看:
resId:0
resId:3
resId:2
resId:1
resId:4
resId:5
resId:7
resId:6
resId:8
resId:9
resId:10
resId:11
resId:12
resId:13
resId:14
resId:15
resId:16
resId:17
resId:18
resId:19
公平设置后,被阻塞的线程就会按照先进先出的顺序获得许可,因此,后面10个线程是顺序打印Id信息的。