Java中的Semaphore被用于多线程环境中,用于控制在多线程环境下,同一资源被并发访问的线程数。如示例代码中设置了并发访问线程数为3,线程池中存在10个任务需要执行,那么当3个并发访问数已满时,其他线程 需要等待已获取的许可的线程释放许可后 才能继续执行。
根据JDK文档可以看出Semaphore与Lock不太相同,可以由线程释放“锁定”,而不是由所有者(因为信号量没有所有权的概念)。在某些专门的上下文(如死锁恢复)中这会很有用。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
public class SemaphoreTest
{
public static void main(String[] args)
{
final ExecutorService threadPool = Executors.newCachedThreadPool();
/*
* new Semaphore(int permits);
* 设置permits创建允许最大permits个并发访问数的Semaphore对象
*
* new Semaphore(int permits, boolean fair);
* 如果使用两个参数的构造方法创建Semaphore对象
* 并将fair设置为true则Semaphore会保证先进先出的规则
* 否则随机授予许可
*/
final Semaphore sp = new Semaphore(3);
System.out.println("测试即将开始...");
//创建10个任务 依次放入线程池中
for(int i = 0; i < 10; i++)
{
Runnable thread = new Runnable()
{
@Override
public void run()
{
try
{
//获取许可
sp.acquire();
}
catch (InterruptedException e)
{
}
try
{
Thread.sleep((long) (Math.random() * 10000));
}
catch (InterruptedException e)
{
}
//打印获取许可的线程信息 sp.availablePermits()表示当前可用的许可
System.out.println("线程:" + Thread.currentThread().getName()
+ "已进入 当前有"+ (3 - sp.availablePermits()) + "个线程正在使用许可。");
sp.release();
//此句代码有可能会出现执行不准确的现象,因为在执行这句代码的同时 有可能其他线程在获取或释放许可
System.out.println("线程 :" + Thread.currentThread().getName() +
"已退出,并释放许可。当前有" + (3 - sp.availablePermits()) + "个线程正在使用许可。" );
}
};
threadPool.execute(thread);
}
threadPool.shutdown();
while(true)
{
if(threadPool.isTerminated())
{
System.out.println("测试结束。");
break;
}
}
}
}