1.案例分析:
(1)100个线程运行一段程序,要求同时只能有10个线程运行
(2) 抢车位:有3个停车位,但是有6个车需要停,模拟抢夺过程
2.代码实现:
(1)需求1代码实现
package com.example.test;
import java.util.Random;
import java.util.concurrent.Semaphore;
public class semaphore {
private final static Semaphore MAX_SEMA_PHORE = new Semaphore(10);
public static void main(String []args) {
for(int i = 0 ; i < 100 ; i++) {
final int num = i;
final Random radom = new Random();
new Thread() {
public void run() {
boolean acquired = false;
try {
MAX_SEMA_PHORE.acquire();
acquired = true;
System.out.println("我是线程:" + num + " 我获得了使用权!" );
long time = 1000 * Math.max(1, Math.abs(radom.nextInt() % 10));
Thread.sleep(time);
System.out.println("我是线程:" + num + " 我执行完了!" );
}catch(Exception e) {
e.printStackTrace();
}finally {
if(acquired) {
MAX_SEMA_PHORE.release();
}
}
}
}.start();
}
}
}
运行结果:
(2)需求2 代码实现:
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
public class SemaphoreDemo {
/**
* 模拟抢车位:6辆车,抢3个车位
*/
public static void main(String[] args) {
Semaphore semaphore = new Semaphore(3); //模拟3个车位
for (int i = 0; i < 6; i++) {
new Thread(()->{
try {
//强到车位
semaphore.acquire();
System.out.println(Thread.currentThread().getName()+"\t抢到了车位");
//模拟停车3s
TimeUnit.SECONDS.sleep(3);
System.out.println(Thread.currentThread().getName()+"\t停车3s后离开车位");
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
//停了3s后离开车位
semaphore.release();
}
},String.valueOf(i)).start();
}
}
}
3.代码解读:
发现没有,上述控制资源所采用的方法是信号量,semaphore,当线程运行一段时间后,会释放信号,然后就有新的线程进入,线程数始终维持在我们设定的数量值。 信号量可以理解为对锁的扩展,无论是内部锁synchronized还是重入锁ReentrantLock,一次只允许一个线程访问一个资源,而信号量却可以指定多个线程,同时访问同一个资源。
Semaphore提供的构造器
public Semaphore(int permits) {
sync = new NonfairSync(permits);
}
//参数permits:许可数目,即同时可以允许多少线程进行访问//参数fair:是否是公平的,即等待时间越久的越先获取许可
public Semaphore(int permits, boolean fair) {
sync = fair ? new FairSync(permits) : new NonfairSync(permits);
}
Semaphore中比较重要的方法
//获得一个许可public void acquire() throws InterruptedException {
sync.acquireSharedInterruptibly(1);}
//获取permits个许可public void acquire(int permits) throws InterruptedException {
if (permits < 0) throw new IllegalArgumentException();
sync.acquireSharedInterruptibly(permits);}
//释放一个许可public void release() {
sync.releaseShared(1);}
//释放permits个许可public void release(int permits) {
if (permits < 0) throw new IllegalArgumentException();
sync.releaseShared(permits);}
//尝试获取一个许可,若获取成功,则立即返回true,若获取失败,则立即返回falsepublic boolean tryAcquire() {
return sync.nonfairTryAcquireShared(1) >= 0;}
//尝试获取permits个许可,若获取成功,则立即返回true,若获取失败,则立即返回falsepublic boolean tryAcquire(int permits) {
if (permits < 0) throw new IllegalArgumentException();
return sync.nonfairTryAcquireShared(permits) >= 0;}
//尝试获取一个许可,若在指定的时间内获取成功,则立即返回true,否则则立即返回falsepublic boolean tryAcquire(long timeout, TimeUnit unit) throws InterruptedException {
return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));}
//尝试获取permits个许可,若在指定的时间内获取成功,则立即返回true,否则则立即返回falsepublic boolean tryAcquire(int permits, long timeout, TimeUnit unit) throws InterruptedException {
if (permits < 0) throw new IllegalArgumentException();
return sync.tryAcquireSharedNanos(permits, unit.toNanos(timeout));}